1 // (C) 2018 Michael Toutonghi
\r
2 // Distributed under the MIT software license, see the accompanying
\r
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
\r
6 This provides the PoW hash function for Verus, enabling CPU mining.
\r
8 #ifndef VERUS_HASH_H_
\r
9 #define VERUS_HASH_H_
\r
16 #include "crypto/verus_clhash.h"
\r
20 #include "crypto/haraka.h"
\r
21 #include "crypto/haraka_portable.h"
\r
27 static void Hash(void *result, const void *data, size_t len);
\r
28 static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
\r
34 CVerusHash &Write(const unsigned char *data, size_t len);
\r
41 std::fill(buf1, buf1 + sizeof(buf1), 0);
\r
45 int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
\r
50 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
\r
53 void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
\r
55 void Finalize(unsigned char hash[32])
\r
59 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
\r
60 (*haraka512Function)(hash, curBuf);
\r
63 std::memcpy(hash, curBuf, 32);
\r
67 // only buf1, the first source, needs to be zero initialized
\r
68 unsigned char buf1[64] = {0}, buf2[64];
\r
69 unsigned char *curBuf = buf1, *result = buf2;
\r
76 static void Hash(void *result, const void *data, size_t len);
\r
77 static void (*haraka512Function)(unsigned char *out, const unsigned char *in);
\r
78 static void (*haraka512KeyedFunction)(unsigned char *out, const unsigned char *in, const u128 *rc);
\r
79 static void (*haraka256Function)(unsigned char *out, const unsigned char *in);
\r
85 CVerusHashV2() : vclh() {
\r
86 // we must have allocated key space, or can't run
\r
87 if (verusclhasher_keySizeInBytes == 0)
\r
89 printf("ERROR: failed to allocate hash buffer - terminating\n");
\r
94 CVerusHashV2 &Write(const unsigned char *data, size_t len);
\r
96 CVerusHashV2 &Reset()
\r
101 std::fill(buf1, buf1 + sizeof(buf1), 0);
\r
104 int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }
\r
105 inline void ClearExtra()
\r
109 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
\r
112 void FillExtra(const unsigned char *data, size_t len)
\r
116 int left = 32 - curPos;
\r
119 std::memcpy(curBuf + 32 + curPos, data, left > len ? len : left);
\r
121 } while (left > 0);
\r
124 inline void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }
\r
126 void Finalize(unsigned char hash[32])
\r
130 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);
\r
131 (*haraka512Function)(hash, curBuf);
\r
134 std::memcpy(hash, curBuf, 32);
\r
137 // chains Haraka256 from 32 bytes to fill the key
\r
138 void GenNewCLKey(unsigned char *seedBytes32)
\r
140 // generate a new key by chain hashing with Haraka256 from the last curbuf
\r
141 int n256blks = verusclhasher_keySizeInBytes >> 8;
\r
142 int nbytesExtra = verusclhasher_keySizeInBytes & 0xff;
\r
143 unsigned char *pkey = (unsigned char *)verusclhasher_random_data_;
\r
144 unsigned char *psrc = seedBytes32;
\r
145 for (int i = 0; i < n256blks; i++)
\r
147 (*haraka256Function)(pkey, psrc);
\r
153 unsigned char buf[32];
\r
154 (*haraka256Function)(buf, psrc);
\r
155 memcpy(pkey, buf, nbytesExtra);
\r
159 void Finalize2b(unsigned char hash[32])
\r
163 // gen new key with what is last in buffer
\r
164 GenNewCLKey(curBuf);
\r
166 // run verusclhash on the buffer
\r
167 uint64_t intermediate = vclh(curBuf);
\r
169 // fill buffer to the end with the result
\r
170 FillExtra((const unsigned char *)intermediate, sizeof(intermediate));
\r
172 // get the final hash with a dynamic key for each hash result
\r
173 (*haraka512KeyedFunction)((unsigned char*)&result, curBuf, (u128 *)verusclhasher_random_data_ + (intermediate & 0xf));
\r
176 inline unsigned char *CurBuffer()
\r
182 // only buf1, the first source, needs to be zero initialized
\r
183 alignas(128) unsigned char buf1[64] = {0}, buf2[64];
\r
184 unsigned char *curBuf = buf1, *result = buf2;
\r
188 extern void verus_hash(void *result, const void *data, size_t len);
\r
189 extern void verus_hash_v2(void *result, const void *data, size_t len);
\r
191 inline bool IsCPUVerusOptimized()
\r
193 unsigned int eax,ebx,ecx,edx;
\r
195 if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx))
\r
199 return ((ecx & (bit_AVX | bit_AES | bit_PCLMUL)) == (bit_AVX | bit_AES | bit_PCLMUL));
\r