]> Git Repo - VerusCoin.git/blob - src/crypto/verus_hash.h
Algorithm concepts
[VerusCoin.git] / src / crypto / verus_hash.h
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
4 \r
5 /*\r
6 This provides the PoW hash function for Verus, enabling CPU mining.\r
7 */\r
8 #ifndef VERUS_HASH_H_\r
9 #define VERUS_HASH_H_\r
10 \r
11 #include <cstring>\r
12 #include <vector>\r
13 \r
14 #include <cpuid.h>\r
15 \r
16 #include "crypto/verus_clhash.h"\r
17 \r
18 extern "C" \r
19 {\r
20 #include "crypto/haraka.h"\r
21 #include "crypto/haraka_portable.h"\r
22 }\r
23 \r
24 class CVerusHash\r
25 {\r
26     public:\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
29 \r
30         static void init();\r
31 \r
32         CVerusHash() { }\r
33 \r
34         CVerusHash &Write(const unsigned char *data, size_t len);\r
35 \r
36         CVerusHash &Reset()\r
37         {\r
38             curBuf = buf1;\r
39             result = buf2;\r
40             curPos = 0;\r
41             std::fill(buf1, buf1 + sizeof(buf1), 0);\r
42             return *this;\r
43         }\r
44 \r
45         int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }\r
46         void ClearExtra()\r
47         {\r
48             if (curPos)\r
49             {\r
50                 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);\r
51             }\r
52         }\r
53         void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }\r
54 \r
55         void Finalize(unsigned char hash[32])\r
56         {\r
57             if (curPos)\r
58             {\r
59                 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);\r
60                 (*haraka512Function)(hash, curBuf);\r
61             }\r
62             else\r
63                 std::memcpy(hash, curBuf, 32);\r
64         }\r
65 \r
66     private:\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
70         size_t curPos = 0;\r
71 };\r
72 \r
73 class CVerusHashV2\r
74 {\r
75     public:\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
80 \r
81         static void init();\r
82 \r
83         verusclhasher vclh;\r
84 \r
85         CVerusHashV2() : vclh() {\r
86             // we must have allocated key space, or can't run\r
87             if (verusclhasher_keySizeInBytes == 0)\r
88             {\r
89                 printf("ERROR: failed to allocate hash buffer - terminating\n");\r
90                 assert(false);\r
91             }\r
92         }\r
93 \r
94         CVerusHashV2 &Write(const unsigned char *data, size_t len);\r
95 \r
96         CVerusHashV2 &Reset()\r
97         {\r
98             curBuf = buf1;\r
99             result = buf2;\r
100             curPos = 0;\r
101             std::fill(buf1, buf1 + sizeof(buf1), 0);\r
102         }\r
103 \r
104         int64_t *ExtraI64Ptr() { return (int64_t *)(curBuf + 32); }\r
105         inline void ClearExtra()\r
106         {\r
107             if (curPos)\r
108             {\r
109                 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);\r
110             }\r
111         }\r
112         void FillExtra(const unsigned char *data, size_t len)\r
113         {\r
114             if (curPos)\r
115             {\r
116                 int left = 32 - curPos;\r
117                 do\r
118                 {\r
119                     std::memcpy(curBuf + 32 + curPos, data, left > len ? len : left);\r
120                     left -= len;\r
121                 } while (left > 0);\r
122             }\r
123         }\r
124         inline void ExtraHash(unsigned char hash[32]) { (*haraka512Function)(hash, curBuf); }\r
125 \r
126         void Finalize(unsigned char hash[32])\r
127         {\r
128             if (curPos)\r
129             {\r
130                 std::fill(curBuf + 32 + curPos, curBuf + 64, 0);\r
131                 (*haraka512Function)(hash, curBuf);\r
132             }\r
133             else\r
134                 std::memcpy(hash, curBuf, 32);\r
135         }\r
136 \r
137         // chains Haraka256 from 32 bytes to fill the key\r
138         void GenNewCLKey(unsigned char *seedBytes32)\r
139         {\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
146             {\r
147                 (*haraka256Function)(pkey, psrc);\r
148                 psrc = pkey;\r
149                 pkey++;\r
150             }\r
151             if (nbytesExtra)\r
152             {\r
153                 unsigned char buf[32];\r
154                 (*haraka256Function)(buf, psrc);\r
155                 memcpy(pkey, buf, nbytesExtra);\r
156             }\r
157         }\r
158 \r
159         void Finalize2b(unsigned char hash[32])\r
160         {\r
161             ClearExtra();\r
162 \r
163             // gen new key with what is last in buffer\r
164             GenNewCLKey(curBuf);\r
165 \r
166             // run verusclhash on the buffer\r
167             uint64_t intermediate = vclh(curBuf);\r
168 \r
169             // fill buffer to the end with the result\r
170             FillExtra((const unsigned char *)intermediate, sizeof(intermediate));\r
171 \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
174         }\r
175 \r
176         inline unsigned char *CurBuffer()\r
177         {\r
178             return curBuf;\r
179         }\r
180 \r
181     private:\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
185         size_t curPos = 0;\r
186 };\r
187 \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
190 \r
191 inline bool IsCPUVerusOptimized()\r
192 {\r
193     unsigned int eax,ebx,ecx,edx;\r
194 \r
195     if (!__get_cpuid(1,&eax,&ebx,&ecx,&edx))\r
196     {\r
197         return false;\r
198     }\r
199     return ((ecx & (bit_AVX | bit_AES | bit_PCLMUL)) == (bit_AVX | bit_AES | bit_PCLMUL));\r
200 };\r
201 \r
202 #endif\r
This page took 0.037509 seconds and 4 git commands to generate.