From 4dcb64c08101e5d37427702abd6107a54be7c6ce Mon Sep 17 00:00:00 2001 From: Michael Toutonghi Date: Tue, 26 Jun 2018 07:39:50 -0700 Subject: [PATCH] Radical hash rate optimization --- src/Makefile.am | 13 +++++- src/crypto/haraka.c | 32 +++++++++++++++ src/crypto/haraka.h | 11 +++++ src/crypto/haraka_portable.c | 59 +++++++++++++++++++++++++++ src/crypto/haraka_portable.h | 9 +++++ src/crypto/verus_hash.cpp | 61 +++++++++++++++++++++------- src/crypto/verus_hash.h | 39 +++++++++++++++--- src/hash.h | 78 ++++++------------------------------ src/init.cpp | 12 ++---- src/komodo_globals.h | 6 +-- src/miner.cpp | 57 +++++++++++++------------- src/pow.cpp | 16 +++++++- src/primitives/block.cpp | 18 +-------- src/primitives/block.h | 9 ++--- src/primitives/transaction.h | 2 +- 15 files changed, 271 insertions(+), 151 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 3cfaa7066..fbc8bf73d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -164,9 +164,10 @@ BITCOIN_CORE_H = \ consensus/validation.h \ core_io.h \ core_memusage.h \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ deprecation.h \ - haraka.h \ - haraka_portable.h \ hash.h \ httprpc.h \ httpserver.h \ @@ -266,6 +267,9 @@ libbitcoin_server_a_SOURCES = \ cc/betprotocol.cpp \ chain.cpp \ checkpoints.cpp \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ deprecation.cpp \ httprpc.cpp \ httpserver.cpp \ @@ -363,6 +367,8 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h \ + crypto/haraka.h \ + crypto/haraka_portable.h \ crypto/verus_hash.h \ crypto/verus_hash.cpp @@ -400,6 +406,9 @@ libbitcoin_common_a_SOURCES = \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ + crypto/haraka.h \ + crypto/haraka_portable.h \ + crypto/verus_hash.h \ hash.cpp \ key.cpp \ keystore.cpp \ diff --git a/src/crypto/haraka.c b/src/crypto/haraka.c index ccfd8ce34..d611b9af5 100644 --- a/src/crypto/haraka.c +++ b/src/crypto/haraka.c @@ -28,6 +28,7 @@ Optimized Implementations for Haraka256 and Haraka512 #include "crypto/haraka.h" u128 rc[40]; +u128 rc0[40] = {0}; void load_constants() { rc[0] = _mm_set_epi32(0x0684704c,0xe620c00a,0xb2c5fef0,0x75817b9d); @@ -365,6 +366,37 @@ void haraka512(unsigned char *out, const unsigned char *in) { TRUNCSTORE(out, s[0], s[1], s[2], s[3]); } +void haraka512_zero(unsigned char *out, const unsigned char *in) { + u128 s[4], tmp; + + s[0] = LOAD(in); + s[1] = LOAD(in + 16); + s[2] = LOAD(in + 32); + s[3] = LOAD(in + 48); + + AES4_zero(s[0], s[1], s[2], s[3], 0); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 8); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 16); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 24); + MIX4(s[0], s[1], s[2], s[3]); + + AES4_zero(s[0], s[1], s[2], s[3], 32); + MIX4(s[0], s[1], s[2], s[3]); + + s[0] = _mm_xor_si128(s[0], LOAD(in)); + s[1] = _mm_xor_si128(s[1], LOAD(in + 16)); + s[2] = _mm_xor_si128(s[2], LOAD(in + 32)); + s[3] = _mm_xor_si128(s[3], LOAD(in + 48)); + + TRUNCSTORE(out, s[0], s[1], s[2], s[3]); +} + void haraka512_4x(unsigned char *out, const unsigned char *in) { u128 s[4][4], tmp; diff --git a/src/crypto/haraka.h b/src/crypto/haraka.h index 1cb5ea662..daf657184 100644 --- a/src/crypto/haraka.h +++ b/src/crypto/haraka.h @@ -68,6 +68,16 @@ extern u128 rc[40]; s2 = _mm_aesenc_si128(s2, rc[rci + 6]); \ s3 = _mm_aesenc_si128(s3, rc[rci + 7]); \ +#define AES4_zero(s0, s1, s2, s3, rci) \ + s0 = _mm_aesenc_si128(s0, rc0[rci]); \ + s1 = _mm_aesenc_si128(s1, rc0[rci + 1]); \ + s2 = _mm_aesenc_si128(s2, rc0[rci + 2]); \ + s3 = _mm_aesenc_si128(s3, rc0[rci + 3]); \ + s0 = _mm_aesenc_si128(s0, rc0[rci + 4]); \ + s1 = _mm_aesenc_si128(s1, rc0[rci + 5]); \ + s2 = _mm_aesenc_si128(s2, rc0[rci + 6]); \ + s3 = _mm_aesenc_si128(s3, rc0[rci + 7]); \ + #define AES4_4x(s0, s1, s2, s3, rci) \ AES4(s0[0], s0[1], s0[2], s0[3], rci); \ AES4(s1[0], s1[1], s1[2], s1[3], rci); \ @@ -109,6 +119,7 @@ void haraka256_4x(unsigned char *out, const unsigned char *in); void haraka256_8x(unsigned char *out, const unsigned char *in); void haraka512(unsigned char *out, const unsigned char *in); +void haraka512_zero(unsigned char *out, const unsigned char *in); void haraka512_4x(unsigned char *out, const unsigned char *in); void haraka512_8x(unsigned char *out, const unsigned char *in); diff --git a/src/crypto/haraka_portable.c b/src/crypto/haraka_portable.c index 66b1c2c16..0792f8b2f 100644 --- a/src/crypto/haraka_portable.c +++ b/src/crypto/haraka_portable.c @@ -53,6 +53,7 @@ static const unsigned char haraka_rc[40][16] = { }; static unsigned char rc[40][16]; +static unsigned char rc0[40][16]; static unsigned char rc_sseed[40][16]; static const unsigned char sbox[256] = @@ -121,6 +122,12 @@ void unpackhi32(unsigned char *t, unsigned char *a, unsigned char *b) memcpy(t, tmp, 16); } +void load_constants_port() +{ + /* Use the standard constants to generate tweaked ones. */ + memcpy(rc, haraka_rc, 40*16); +} + void tweak_constants(const unsigned char *pk_seed, const unsigned char *sk_seed, unsigned long long seed_length) { @@ -258,6 +265,58 @@ void haraka512_port(unsigned char *out, const unsigned char *in) memcpy(out + 24, buf + 48, 8); } +void haraka512_perm_zero(unsigned char *out, const unsigned char *in) +{ + int i, j; + + unsigned char s[64], tmp[16]; + + memcpy(s, in, 16); + memcpy(s + 16, in + 16, 16); + memcpy(s + 32, in + 32, 16); + memcpy(s + 48, in + 48, 16); + + for (i = 0; i < 5; ++i) { + // aes round(s) + for (j = 0; j < 2; ++j) { + aesenc(s, rc0[4*2*i + 4*j]); + aesenc(s + 16, rc0[4*2*i + 4*j + 1]); + aesenc(s + 32, rc0[4*2*i + 4*j + 2]); + aesenc(s + 48, rc0[4*2*i + 4*j + 3]); + } + + // mixing + unpacklo32(tmp, s, s + 16); + unpackhi32(s, s, s + 16); + unpacklo32(s + 16, s + 32, s + 48); + unpackhi32(s + 32, s + 32, s + 48); + unpacklo32(s + 48, s, s + 32); + unpackhi32(s, s, s + 32); + unpackhi32(s + 32, s + 16, tmp); + unpacklo32(s + 16, s + 16, tmp); + } + + memcpy(out, s, 64); +} + +void haraka512_port_zero(unsigned char *out, const unsigned char *in) +{ + int i; + + unsigned char buf[64]; + + haraka512_perm_zero(buf, in); + /* Feed-forward */ + for (i = 0; i < 64; i++) { + buf[i] = buf[i] ^ in[i]; + } + + /* Truncated */ + memcpy(out, buf + 8, 8); + memcpy(out + 8, buf + 24, 8); + memcpy(out + 16, buf + 32, 8); + memcpy(out + 24, buf + 48, 8); +} void haraka256_port(unsigned char *out, const unsigned char *in) { diff --git a/src/crypto/haraka_portable.h b/src/crypto/haraka_portable.h index ac708ee9a..dcc4f65ae 100644 --- a/src/crypto/haraka_portable.h +++ b/src/crypto/haraka_portable.h @@ -1,6 +1,9 @@ #ifndef SPX_HARAKA_H #define SPX_HARAKA_H +/* load constants */ +void load_constants_port(); + /* Tweak constants with seed */ void tweak_constants(const unsigned char *pk_seed, const unsigned char *sk_seed, unsigned long long seed_length); @@ -15,6 +18,12 @@ void haraka512_perm(unsigned char *out, const unsigned char *in); /* Implementation of Haraka-512 */ void haraka512_port(unsigned char *out, const unsigned char *in); +/* Applies the 512-bit Haraka permutation to in, using zero key. */ +void haraka512_perm_zero(unsigned char *out, const unsigned char *in); + +/* Implementation of Haraka-512, using zero key */ +void haraka512_port_zero(unsigned char *out, const unsigned char *in); + /* Implementation of Haraka-256 */ void haraka256_port(unsigned char *out, const unsigned char *in); diff --git a/src/crypto/verus_hash.cpp b/src/crypto/verus_hash.cpp index c8b88d48d..459872be3 100644 --- a/src/crypto/verus_hash.cpp +++ b/src/crypto/verus_hash.cpp @@ -12,6 +12,8 @@ bit output. #include "crypto/common.h" #include "crypto/verus_hash.h" +void (*CVerusHash::haraka512Function)(unsigned char *out, const unsigned char *in); + void CVerusHash::Hash(void *result, const void *data, size_t len) { unsigned char buf[128]; @@ -36,7 +38,7 @@ void CVerusHash::Hash(void *result, const void *data, size_t len) memcpy(bufPtr + 32, ptr + pos, i); memset(bufPtr + 32 + i, 0, 32 - i); } - haraka512(bufPtr2, bufPtr); + (*haraka512Function)(bufPtr2, bufPtr); bufPtr2 = bufPtr; bufPtr += nextOffset; nextOffset *= -1; @@ -44,6 +46,18 @@ void CVerusHash::Hash(void *result, const void *data, size_t len) memcpy(result, bufPtr, 32); }; +void CVerusHash::init() +{ + if (IsCPUVerusOptimized()) + { + haraka512Function = &haraka512_zero; + } + else + { + haraka512Function = &haraka512_port_zero; + } +} + CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) { unsigned char *tmp; @@ -56,7 +70,7 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) if (len - pos >= room) { memcpy(curBuf + 32 + curPos, data + pos, room); - haraka512(result, curBuf); + (*haraka512Function)(result, curBuf); tmp = curBuf; curBuf = result; result = tmp; @@ -73,7 +87,31 @@ CVerusHash &CVerusHash::Write(const unsigned char *data, size_t len) return *this; } -void CVerusHashPortable::Hash(void *result, const void *data, size_t len) +// to be declared and accessed from C +void verus_hash(void *result, const void *data, size_t len) +{ + return CVerusHash::Hash(result, data, len); +} + +void (*CVerusHashV2::haraka512Function)(unsigned char *out, const unsigned char *in); + +void CVerusHashV2::init() +{ + // load and tweak the haraka constants + load_constants(); + load_constants_port(); + + if (IsCPUVerusOptimized()) + { + haraka512Function = &haraka512; + } + else + { + haraka512Function = &haraka512_port; + } +} + +void CVerusHashV2::Hash(void *result, const void *data, size_t len) { unsigned char buf[128]; unsigned char *bufPtr = buf; @@ -97,7 +135,7 @@ void CVerusHashPortable::Hash(void *result, const void *data, size_t len) memcpy(bufPtr + 32, ptr + pos, i); memset(bufPtr + 32 + i, 0, 32 - i); } - haraka512_port(bufPtr2, bufPtr); + (*haraka512Function)(bufPtr2, bufPtr); bufPtr2 = bufPtr; bufPtr += nextOffset; nextOffset *= -1; @@ -105,7 +143,7 @@ void CVerusHashPortable::Hash(void *result, const void *data, size_t len) memcpy(result, bufPtr, 32); }; -CVerusHashPortable &CVerusHashPortable::Write(const unsigned char *data, size_t len) +CVerusHashV2 &CVerusHashV2::Write(const unsigned char *data, size_t len) { unsigned char *tmp; @@ -117,7 +155,7 @@ CVerusHashPortable &CVerusHashPortable::Write(const unsigned char *data, size_t if (len - pos >= room) { memcpy(curBuf + 32 + curPos, data + pos, room); - haraka512_port(result, curBuf); + (*haraka512Function)(result, curBuf); tmp = curBuf; curBuf = result; result = tmp; @@ -135,14 +173,7 @@ CVerusHashPortable &CVerusHashPortable::Write(const unsigned char *data, size_t } // to be declared and accessed from C -void verus_hash(void *result, const void *data, size_t len) +void verus_hash_v2(void *result, const void *data, size_t len) { - return CVerusHashPortable::Hash(result, data, len); + return CVerusHashV2::Hash(result, data, len); } - -// to be declared and accessed from C -void verus_hash_optimized(void *result, const void *data, size_t len) -{ - return CVerusHash::Hash(result, data, len); -} - diff --git a/src/crypto/verus_hash.h b/src/crypto/verus_hash.h index 85f3c4830..33fc0ce5d 100644 --- a/src/crypto/verus_hash.h +++ b/src/crypto/verus_hash.h @@ -23,6 +23,9 @@ class CVerusHash { public: static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); + + static void init(); CVerusHash() {} @@ -36,12 +39,22 @@ class CVerusHash std::fill(buf1, buf1 + sizeof(buf1), 0); } + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + void Finalize(unsigned char hash[32]) { if (curPos) { std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - haraka512(hash, curBuf); + (*haraka512Function)(hash, curBuf); } else std::memcpy(hash, curBuf, 32); @@ -54,16 +67,19 @@ class CVerusHash size_t curPos = 0; }; -class CVerusHashPortable +class CVerusHashV2 { public: static void Hash(void *result, const void *data, size_t len); + static void (*haraka512Function)(unsigned char *out, const unsigned char *in); - CVerusHashPortable() {} + static void init(); - CVerusHashPortable &Write(const unsigned char *data, size_t len); + CVerusHashV2() {} - CVerusHashPortable &Reset() + CVerusHashV2 &Write(const unsigned char *data, size_t len); + + CVerusHashV2 &Reset() { curBuf = buf1; result = buf2; @@ -71,12 +87,22 @@ class CVerusHashPortable std::fill(buf1, buf1 + sizeof(buf1), 0); } + int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); } + void ClearExtra() + { + if (curPos) + { + std::fill(curBuf + 32 + curPos, curBuf + 64, 0); + } + } + void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); } + void Finalize(unsigned char hash[32]) { if (curPos) { std::fill(curBuf + 32 + curPos, curBuf + 64, 0); - haraka512_port(hash, curBuf); + (*haraka512Function)(hash, curBuf); } else std::memcpy(hash, curBuf, 32); @@ -90,6 +116,7 @@ class CVerusHashPortable }; extern void verus_hash(void *result, const void *data, size_t len); +extern void verus_hash_v2(void *result, const void *data, size_t len); inline bool IsCPUVerusOptimized() { diff --git a/src/hash.h b/src/hash.h index db2c31f2a..1a129b720 100644 --- a/src/hash.h +++ b/src/hash.h @@ -217,6 +217,9 @@ public: return result; } + int64_t *xI64p() { return state.ExtraI64Ptr(); } + CVerusHash &GetState() { return state; } + template CVerusHashWriter& operator<<(const T& obj) { // Serialize to this stream @@ -225,19 +228,19 @@ public: } }; -/** A writer stream (for serialization) that computes a 256-bit Verus hash. */ -class CVerusHashPortableWriter +/** A writer stream (for serialization) that computes a 256-bit Verus hash with key initialized to Haraka standard. */ +class CVerusHashV2Writer { private: - CVerusHashPortable state; + CVerusHashV2 state; public: int nType; int nVersion; - CVerusHashPortableWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} + CVerusHashV2Writer(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), state() {} - CVerusHashPortableWriter& write(const char *pch, size_t size) { + CVerusHashV2Writer& write(const char *pch, size_t size) { state.Write((const unsigned char*)pch, size); return (*this); } @@ -249,57 +252,11 @@ public: return result; } - template - CVerusHashPortableWriter& operator<<(const T& obj) { - // Serialize to this stream - ::Serialize(*this, obj, nType, nVersion); - return (*this); - } -}; - -/** An optimized and dangerous writer stream (for serialization) that computes a 256-bit Verus hash without the normal - * safety checks. Do not try to write more than 1488 bytes to this hash writer. */ -class CVerusMiningHashWriter -{ -public: - union hwBuf { - unsigned char charBuf[1488]; - int32_t i32a[522]; - hwBuf() - { - memset(charBuf, 0, sizeof(charBuf)); - } - }; - hwBuf buf; - int nPos; - int nType; - int nVersion; - - CVerusMiningHashWriter(int nTypeIn, int nVersionIn, int pos = 0) : buf() - { - nPos = pos; - nType = nTypeIn; - nVersion = nVersionIn; - } - - CVerusMiningHashWriter& write(const char *pch, size_t size) { - if ((nPos + size) <= sizeof(buf.charBuf)) - { - memcpy(&(buf.charBuf[nPos]), pch, size); - nPos += size; - } - return (*this); - } - - // does not invalidate the object for modification and further hashing - uint256 GetHash() { - uint256 result; - CVerusHash::Hash((unsigned char*)&result, buf.charBuf, nPos); - return result; - } + int64_t *xI64p() { return state.ExtraI64Ptr(); } + CVerusHashV2 &GetState() { return state; } template - CVerusMiningHashWriter& operator<<(const T& obj) { + CVerusHashV2Writer& operator<<(const T& obj) { // Serialize to this stream ::Serialize(*this, obj, nType, nVersion); return (*this); @@ -326,18 +283,9 @@ uint256 SerializeVerusHash(const T& obj, int nType=SER_GETHASH, int nVersion=PRO /** Compute the 256-bit Verus hash of an object's serialization. */ template -uint256 SerializeVerusHashPortable(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) +uint256 SerializeVerusHashV2(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) { - CVerusHashPortableWriter ss(nType, nVersion); - ss << obj; - return ss.GetHash(); -} - -/** Compute the 256-bit Verus hash of an object's serialization. */ -template -uint256 SerializeVerusMiningHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION) -{ - CVerusMiningHashWriter ss = CVerusMiningHashWriter(nType, nVersion); + CVerusHashV2Writer ss(nType, nVersion); ss << obj; return ss.GetHash(); } diff --git a/src/init.cpp b/src/init.cpp index b4d542c56..77967c96e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1104,14 +1104,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH; if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH) { - // if we must run portable, do so - if (IsCPUVerusOptimized()) - { - CBlockHeader::SetVerusHash(); - } - else{ - CBlockHeader::SetVerusHashPortable(); - } + // initialize VerusHash + CVerusHash::init(); + CVerusHashV2::init(); + CBlockHeader::SetVerusHash(); } // Sanity check diff --git a/src/komodo_globals.h b/src/komodo_globals.h index d4609d844..f37573e04 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -73,9 +73,9 @@ uint32_t ASSETCHAINS_NUMALGOS = 2; uint32_t ASSETCHAINS_EQUIHASH = _ASSETCHAINS_EQUIHASH; uint32_t ASSETCHAINS_VERUSHASH = 1; const char *ASSETCHAINS_ALGORITHMS[] = {"equihash", "verushash"}; -uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xffffff}; -uint32_t ASSETCHAINS_NONCESHIFT[] = {32,40}; -uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,512}; +uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xfffffff}; +uint32_t ASSETCHAINS_NONCESHIFT[] = {32,16}; +uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,4096}; uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; // Verus proof of stake controls diff --git a/src/miner.cpp b/src/miner.cpp index 3e778cc78..d8590e9bc 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1148,23 +1148,40 @@ void static BitcoinMiner_noeq() { arith_uint256 arNonce = UintToArith256(pblock->nNonce); - CVerusMiningHashWriter ss = CVerusMiningHashWriter(SER_GETHASH, PROTOCOL_VERSION); + CVerusHashWriter ss = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); ss << *((CBlockHeader *)pblock); + int64_t *extraPtr = ss.xI64p(); + CVerusHash &vh = ss.GetState(); + uint256 hashResult = uint256(); + vh.ClearExtra(); + int64_t count = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1; + int64_t hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; - // for speed check 16 mega hash at a time - for (int i = 0; i < 0x1000000; i++) + // for speed check 4 giga hash at a time + for (int64_t i = 0; i < count; i++) { solutionTargetChecks.increment(); // Update nNonce - ss.buf.charBuf[108] = *((unsigned char *)&(pblock->nNonce)) = i & 0xff; - ss.buf.charBuf[109] = *(((unsigned char *)&(pblock->nNonce))+1) = (i >> 8) & 0xff; - ss.buf.charBuf[110] = *(((unsigned char *)&(pblock->nNonce))+2) = (i >> 16) & 0xff; + //ss.buf.charBuf[108] = *((unsigned char *)&(pblock->nNonce)) = i & 0xff; + //ss.buf.charBuf[109] = *(((unsigned char *)&(pblock->nNonce))+1) = (i >> 8) & 0xff; + //ss.buf.charBuf[110] = *(((unsigned char *)&(pblock->nNonce))+2) = (i >> 16) & 0xff; + *extraPtr = i; + vh.ExtraHash((unsigned char *)&hashResult); - if ( UintToArith256(ss.GetHash()) <= hashTarget ) + if ( UintToArith256(hashResult) <= hashTarget ) { + if (pblock->nSolution.size() != 1344) + { + LogPrintf("ERROR: Block solution is not 1344 bytes as it should be"); + sleep(5); + break; + } + SetThreadPriority(THREAD_PRIORITY_NORMAL); + *((int64_t *)&(pblock->nSolution.data()[pblock->nSolution.size() - 15])) = i; + int32_t unlockTime = komodo_block_unlocktime(Mining_height); int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue); @@ -1177,7 +1194,6 @@ void static BitcoinMiner_noeq() printf("- timelocked until block %i\n", unlockTime); else printf("\n"); - #ifdef ENABLE_WALLET ProcessBlockFound(pblock, *pwallet, reservekey); #else @@ -1187,7 +1203,7 @@ void static BitcoinMiner_noeq() break; } // check periodically if we're stale - if (!(i % ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO])) + if (!--hashesToGo) { if ( pindexPrev != chainActive.Tip() ) { @@ -1198,6 +1214,7 @@ void static BitcoinMiner_noeq() } break; } + hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; } } @@ -1229,23 +1246,12 @@ void static BitcoinMiner_noeq() break; } - if ((UintToArith256(pblock->nNonce) & mask) == mask) - { #ifdef _WIN32 - printf("%llu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); + printf("%llu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); #else - printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); + printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); #endif - break; - } - - pblock->nBits = savebits; - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) - { - // Changing pblock->nTime can change work required on testnet: - hashTarget.SetCompact(pblock->nBits); - } + break; } } } @@ -1747,11 +1753,6 @@ void static BitcoinMiner() { static boost::thread_group* minerThreads = NULL; - if (!IsCPUVerusOptimized() && ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH) - { - nThreads = 0; - } - if (nThreads < 0) nThreads = GetNumCores(); diff --git a/src/pow.cpp b/src/pow.cpp index 9c20f55ad..26d432da8 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -22,6 +22,7 @@ uint32_t komodo_chainactive_timestamp(); extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH; +extern char ASSETCHAINS_SYMBOL[65]; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params); unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); @@ -228,7 +229,20 @@ uint32_t lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus:: if (x) { idx[i].consecutive = false; - idx[i].solveTime = VERUS_BLOCK_POSUNITS * (x + 1); + if (!memcmp(ASSETCHAINS_SYMBOL, "VRSC", 4) && pindexLast->nHeight < 67680) + { + idx[i].solveTime = VERUS_BLOCK_POSUNITS * (x + 1); + } + else + { + int64_t lastSolveTime = 0; + idx[i].solveTime = VERUS_BLOCK_POSUNITS; + for (int64_t j = 0; j < x; j++) + { + lastSolveTime = VERUS_BLOCK_POSUNITS + (lastSolveTime >> 1); + idx[i].solveTime += lastSolveTime; + } + } idx[i].nBits = nBits; } else diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index cb54b1f21..752e94079 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -27,19 +27,10 @@ uint256 CBlockHeader::GetVerusHash() const return SerializeVerusHash(*this); } -uint256 CBlockHeader::GetVerusHashPortable() const -{ - if (hashPrevBlock.IsNull()) - // always use SHA256D for genesis block - return SerializeHash(*this); - else - return SerializeVerusHashPortable(*this); -} - -uint256 CBlockHeader::GetVerusMiningHash() const +uint256 CBlockHeader::GetVerusV2Hash() const { // no check for genesis block and use the optimized hash - return SerializeVerusMiningHash(*this); + return SerializeVerusHashV2(*this); } void CBlockHeader::SetSHA256DHash() @@ -52,11 +43,6 @@ void CBlockHeader::SetVerusHash() CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash; } -void CBlockHeader::SetVerusHashPortable() -{ - CBlockHeader::hashFunction = &CBlockHeader::GetVerusHashPortable; -} - uint256 CBlock::BuildMerkleTree(bool* fMutated) const { /* WARNING! If you're reading this because you're learning about crypto diff --git a/src/primitives/block.h b/src/primitives/block.h index 801307b97..fb92952f1 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -84,10 +84,7 @@ public: uint256 GetVerusHash() const; static void SetVerusHash(); - uint256 GetVerusHashPortable() const; - static void SetVerusHashPortable(); - - uint256 GetVerusMiningHash() const; + uint256 GetVerusV2Hash() const; int64_t GetBlockTime() const { @@ -110,14 +107,14 @@ public: { arith_uint256 arNonce = UintToArith256(nNonce); arith_uint256 tmpNonce = ((arNonce << 128) >> 128); - CVerusHashPortableWriter hashWriter = CVerusHashPortableWriter(SER_GETHASH, PROTOCOL_VERSION); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); hashWriter << ArithToUint256(tmpNonce); return (nNonce == ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce)); } void SetVerusPOSTarget(int32_t nBits) { - CVerusHashPortableWriter hashWriter = CVerusHashPortableWriter(SER_GETHASH, PROTOCOL_VERSION); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); uint256 hash; arith_uint256 tmpNonce; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 3c5a3a78f..d7a177fc4 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -476,7 +476,7 @@ public: // verus hash will be the same for a given txid, output number, block height, and blockhash of 100 blocks past static uint256 _GetVerusPOSHash(const uint256 &txid, int32_t voutNum, int32_t height, const uint256 &pastHash, int64_t value) { - CVerusHashPortableWriter hashWriter = CVerusHashPortableWriter(SER_GETHASH, PROTOCOL_VERSION); + CVerusHashWriter hashWriter = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION); hashWriter << ASSETCHAINS_MAGIC; hashWriter << pastHash;