Radical hash rate optimization
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
78
src/hash.h
78
src/hash.h
@@ -217,6 +217,9 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t *xI64p() { return state.ExtraI64Ptr(); }
|
||||
CVerusHash &GetState() { return state; }
|
||||
|
||||
template<typename T>
|
||||
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<typename T>
|
||||
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<typename T>
|
||||
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<typename T>
|
||||
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<typename T>
|
||||
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();
|
||||
}
|
||||
|
||||
12
src/init.cpp
12
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
16
src/pow.cpp
16
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user