OSDN Git Service

test (#52)
[bytom/vapor.git] / mining / tensority / cgo_algorithm / lib / BytomPoW.h
1 /* BytomPoW.h */\r
2 #ifndef BYTOMPOW_H\r
3 #define BYTOMPOW_H\r
4 \r
5 #include "scrypt.h"\r
6 #include "sha3-allInOne.h"\r
7 #include <iostream>\r
8 #include <vector>\r
9 #include <time.h>\r
10 #include <assert.h>\r
11 #include <stdint.h>\r
12 #include <x86intrin.h>\r
13 #include <omp.h>\r
14 \r
15 #define FNV(v1,v2) int32_t( ((v1)*FNV_PRIME) ^ (v2) )\r
16 const int FNV_PRIME = 0x01000193;\r
17 \r
18 struct Mat256x256i8 {\r
19     int8_t d[256][256];\r
20 \r
21     void toIdentityMatrix() {\r
22         for(int i = 0; i < 256; i++) {\r
23             for(int j = 0; j < 256; j++) {\r
24                 d[i][j] = (i==j)?1:0; // diagonal\r
25             }\r
26         }\r
27     }\r
28 \r
29     void copyFrom(const Mat256x256i8& other) {\r
30         for(int i = 0; i < 256; i++) {\r
31             for(int j = 0; j < 256; j++) {\r
32                 this->d[j][i] = other.d[j][i];\r
33             }\r
34         }\r
35     }\r
36 \r
37     Mat256x256i8() {\r
38 //        this->toIdentityMatrix();\r
39     }\r
40 \r
41     Mat256x256i8(const Mat256x256i8& other) {\r
42         this->copyFrom(other);\r
43     }\r
44 \r
45     void copyFrom_helper(LTCMemory& ltcMem, int offset) {\r
46         for(int i = 0; i < 256; i++) {\r
47             const Words32& lo=ltcMem.get(i*4 + offset);\r
48             const Words32& hi=ltcMem.get(i*4 + 2 + offset);\r
49             for(int j = 0; j < 64; j++) {\r
50                 uint32_t i32 = j>=32?hi.get(j-32):lo.get(j);\r
51                 d[j*4+0][i] = (i32>> 0) & 0xFF;\r
52                 d[j*4+1][i] = (i32>> 8) & 0xFF;\r
53                 d[j*4+2][i] = (i32>>16) & 0xFF;\r
54                 d[j*4+3][i] = (i32>>24) & 0xFF;\r
55             }\r
56         }\r
57     }\r
58 \r
59     void copyFromEven(LTCMemory& ltcMem) {\r
60         copyFrom_helper(ltcMem, 0);\r
61     }\r
62 \r
63     void copyFromOdd(LTCMemory& ltcMem) {\r
64         copyFrom_helper(ltcMem, 1);\r
65     }\r
66 \r
67     void add(Mat256x256i8& a, Mat256x256i8& b) {\r
68         for(int i = 0; i < 256; i++) {\r
69             for(int j = 0; j < 256; j++) {\r
70                 int tmp = int(a.d[i][j]) + int(b.d[i][j]);\r
71                 this->d[i][j] = (tmp & 0xFF);\r
72             }\r
73         }\r
74     }\r
75 };\r
76 \r
77 struct Mat256x256i16 {\r
78     int16_t d[256][256];\r
79 \r
80     void toIdentityMatrix() {\r
81         for(int i = 0; i < 256; i++) {\r
82             for(int j = 0; j < 256; j++) {\r
83                 d[i][j] = (i==j?1:0); // diagonal\r
84             }\r
85         }\r
86     }\r
87 \r
88     void copyFrom(const Mat256x256i8& other) {\r
89         for(int i = 0; i < 256; i++) {\r
90             for(int j = 0; j < 256; j++) {\r
91                 this->d[j][i] = int16_t(other.d[j][i]);\r
92                 assert(this->d[j][i] == other.d[j][i]);\r
93             }\r
94         }\r
95     }\r
96 \r
97     void copyFrom(const Mat256x256i16& other) {\r
98         for(int i = 0; i < 256; i++) {\r
99             for(int j = 0; j < 256; j++) {\r
100                 this->d[j][i] = other.d[j][i];\r
101             }\r
102         }\r
103     }\r
104 \r
105     Mat256x256i16() {\r
106 //        this->toIdentityMatrix();\r
107     }\r
108 \r
109     Mat256x256i16(const Mat256x256i16& other) {\r
110         this->copyFrom(other);\r
111     }\r
112 \r
113     void copyFrom_helper(LTCMemory& ltcMem, int offset) {\r
114         for(int i = 0; i < 256; i++) {\r
115             const Words32& lo = ltcMem.get(i*4 + offset);\r
116             const Words32& hi = ltcMem.get(i*4 + 2 + offset);\r
117             for(int j = 0; j < 64; j++) {\r
118                 uint32_t i32 = j>=32?hi.get(j-32):lo.get(j);\r
119                 d[j*4+0][i] = int8_t((i32>> 0) & 0xFF);\r
120                 d[j*4+1][i] = int8_t((i32>> 8) & 0xFF);\r
121                 d[j*4+2][i] = int8_t((i32>>16) & 0xFF);\r
122                 d[j*4+3][i] = int8_t((i32>>24) & 0xFF);\r
123             }\r
124         }\r
125     }\r
126 \r
127     void copyFromEven(LTCMemory& ltcMem) {\r
128         copyFrom_helper(ltcMem, 0);\r
129     }\r
130 \r
131     void copyFromOdd(LTCMemory& ltcMem) {\r
132         copyFrom_helper(ltcMem, 1);\r
133     }\r
134 \r
135     void mul(const Mat256x256i16& a, const Mat256x256i16& b) {\r
136         for(int i = 0; i < 256; i += 16) {\r
137             for(int j = 0; j < 256; j += 16) {\r
138                 for(int ii = i; ii < i+16; ii += 8) {\r
139                     __m256i r[8],s,t[8],u[8],m[8];\r
140                     r[0] = _mm256_set1_epi16(0);\r
141                     r[1] = _mm256_set1_epi16(0);\r
142                     r[2] = _mm256_set1_epi16(0);\r
143                     r[3] = _mm256_set1_epi16(0);\r
144                     r[4] = _mm256_set1_epi16(0);\r
145                     r[5] = _mm256_set1_epi16(0);\r
146                     r[6] = _mm256_set1_epi16(0);\r
147                     r[7] = _mm256_set1_epi16(0);\r
148                     for(int k = 0; k < 256; k++) {\r
149                         s = *((__m256i*)(&(b.d[k][j])));\r
150                         u[0] = _mm256_set1_epi16(a.d[ii+0][k]);\r
151                         u[1] = _mm256_set1_epi16(a.d[ii+1][k]);\r
152                         u[2] = _mm256_set1_epi16(a.d[ii+2][k]);\r
153                         u[3] = _mm256_set1_epi16(a.d[ii+3][k]);\r
154                         u[4] = _mm256_set1_epi16(a.d[ii+4][k]);\r
155                         u[5] = _mm256_set1_epi16(a.d[ii+5][k]);\r
156                         u[6] = _mm256_set1_epi16(a.d[ii+6][k]);\r
157                         u[7] = _mm256_set1_epi16(a.d[ii+7][k]);\r
158                         m[0] = _mm256_mullo_epi16(u[0],s);\r
159                         m[1] = _mm256_mullo_epi16(u[1],s);\r
160                         m[2] = _mm256_mullo_epi16(u[2],s);\r
161                         m[3] = _mm256_mullo_epi16(u[3],s);\r
162                         m[4] = _mm256_mullo_epi16(u[4],s);\r
163                         m[5] = _mm256_mullo_epi16(u[5],s);\r
164                         m[6] = _mm256_mullo_epi16(u[6],s);\r
165                         m[7] = _mm256_mullo_epi16(u[7],s);\r
166                         r[0] = _mm256_add_epi16(r[0],m[0]);\r
167                         r[1] = _mm256_add_epi16(r[1],m[1]);\r
168                         r[2] = _mm256_add_epi16(r[2],m[2]);\r
169                         r[3] = _mm256_add_epi16(r[3],m[3]);\r
170                         r[4] = _mm256_add_epi16(r[4],m[4]);\r
171                         r[5] = _mm256_add_epi16(r[5],m[5]);\r
172                         r[6] = _mm256_add_epi16(r[6],m[6]);\r
173                         r[7] = _mm256_add_epi16(r[7],m[7]);\r
174                     }\r
175                     t[0] = _mm256_slli_epi16(r[0],8);\r
176                     t[1] = _mm256_slli_epi16(r[1],8);\r
177                     t[2] = _mm256_slli_epi16(r[2],8);\r
178                     t[3] = _mm256_slli_epi16(r[3],8);\r
179                     t[4] = _mm256_slli_epi16(r[4],8);\r
180                     t[5] = _mm256_slli_epi16(r[5],8);\r
181                     t[6] = _mm256_slli_epi16(r[6],8);\r
182                     t[7] = _mm256_slli_epi16(r[7],8);\r
183                     t[0] = _mm256_add_epi16(r[0],t[0]);\r
184                     t[1] = _mm256_add_epi16(r[1],t[1]);\r
185                     t[2] = _mm256_add_epi16(r[2],t[2]);\r
186                     t[3] = _mm256_add_epi16(r[3],t[3]);\r
187                     t[4] = _mm256_add_epi16(r[4],t[4]);\r
188                     t[5] = _mm256_add_epi16(r[5],t[5]);\r
189                     t[6] = _mm256_add_epi16(r[6],t[6]);\r
190                     t[7] = _mm256_add_epi16(r[7],t[7]);\r
191                     for(int x = 0; x < 8; x++) {\r
192                         this->d[ii+x][j+0 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*0 +1)));\r
193                         this->d[ii+x][j+1 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*1 +1)));\r
194                         this->d[ii+x][j+2 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*2 +1)));\r
195                         this->d[ii+x][j+3 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*3 +1)));\r
196                         this->d[ii+x][j+4 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*4 +1)));\r
197                         this->d[ii+x][j+5 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*5 +1)));\r
198                         this->d[ii+x][j+6 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*6 +1)));\r
199                         this->d[ii+x][j+7 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*7 +1)));\r
200                         this->d[ii+x][j+8 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*8 +1)));\r
201                         this->d[ii+x][j+9 ] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*9 +1)));\r
202                         this->d[ii+x][j+10] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*10+1)));\r
203                         this->d[ii+x][j+11] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*11+1)));\r
204                         this->d[ii+x][j+12] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*12+1)));\r
205                         this->d[ii+x][j+13] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*13+1)));\r
206                         this->d[ii+x][j+14] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*14+1)));\r
207                         this->d[ii+x][j+15] = int16_t(int8_t(_mm256_extract_epi8(t[x],2*15+1)));\r
208                     }\r
209                 }\r
210             }\r
211         }\r
212     }\r
213 \r
214     void add(Mat256x256i16& a, Mat256x256i16& b) {\r
215         for(int i = 0; i < 256; i++) {\r
216             for(int j = 0; j < 256; j++) {\r
217                 int tmp = int(a.d[i][j]) + int(b.d[i][j]);\r
218                 this->d[i][j] = (tmp & 0xFF);\r
219             }\r
220         }\r
221     }\r
222 \r
223     void toMatI8(Mat256x256i8& other) {\r
224         for(int i = 0; i < 256; i++) {\r
225             for(int j = 0; j < 256; j++) {\r
226                 other.d[j][i] = (this->d[j][i]) & 0xFF;\r
227             }\r
228         }\r
229     }\r
230 \r
231     void topup(Mat256x256i8& other) {\r
232         for(int i = 0; i < 256; i++) {\r
233             for(int j = 0; j < 256; j++) {\r
234                 other.d[j][i] += (this->d[j][i]) & 0xFF;\r
235             }\r
236         }\r
237     }\r
238 };\r
239 \r
240 \r
241 struct Arr256x64i32 {\r
242     uint32_t d[256][64];\r
243 \r
244     uint8_t* d0RawPtr() {\r
245         return (uint8_t*)(d[0]);\r
246     }\r
247 \r
248     Arr256x64i32(const Mat256x256i8& mat) {\r
249         for(int j = 0; j < 256; j++) {\r
250             for(int i = 0; i < 64; i++) {\r
251                 d[j][i] = ((uint32_t(uint8_t(mat.d[j][i + 192]))) << 24) |\r
252                           ((uint32_t(uint8_t(mat.d[j][i + 128]))) << 16) |\r
253                           ((uint32_t(uint8_t(mat.d[j][i +  64]))) <<  8) |\r
254                           ((uint32_t(uint8_t(mat.d[j][i]))) << 0);\r
255             }\r
256         }\r
257     }\r
258 \r
259     void reduceFNV() {\r
260         for(int k = 256; k > 1; k = k/2) {\r
261             for(int j = 0; j < k/2; j++) {\r
262                 for(int i = 0; i < 64; i++) {\r
263                     d[j][i] = FNV(d[j][i], d[j + k/2][i]);\r
264                 }\r
265             }\r
266         }\r
267     }\r
268 };\r
269 \r
270 // struct BytomMatList8 {\r
271 //     std::vector<Mat256x256i8*> matVec;\r
272 \r
273 //     Mat256x256i8 at(int i) {\r
274 //         return *(matVec[i]);\r
275 //     }\r
276 \r
277 //     BytomMatList8() {\r
278 //         for(int i=0; i<256; i++) {\r
279 //             Mat256x256i8* ptr = new Mat256x256i8;\r
280 //             assert(ptr!=NULL);\r
281 //             matVec.push_back(ptr);\r
282 //         }\r
283 //     }\r
284 \r
285 //     ~BytomMatList8() {\r
286 //         for(int i=0; i<256; i++) {\r
287 //             delete matVec[i];\r
288 //         }\r
289 //     }\r
290 \r
291 //     void init(const Words32& X_in) {\r
292 //         Words32 X = X_in;\r
293 //         LTCMemory ltcMem;\r
294 //         for(int i=0; i<128; i++) {\r
295 //             ltcMem.scrypt(X);\r
296 //             matVec[2*i]->copyFromEven(ltcMem);\r
297 //             matVec[2*i+1]->copyFromOdd(ltcMem);\r
298 //         }\r
299 //     }\r
300 // };\r
301 \r
302 struct BytomMatList16 {\r
303     std::vector<Mat256x256i16*> matVec;\r
304 \r
305     Mat256x256i16 at(int i) {\r
306         return *(matVec[i]);\r
307     }\r
308 \r
309     BytomMatList16() {\r
310         for(int i = 0; i < 256; i++) {\r
311             Mat256x256i16* ptr = new Mat256x256i16;\r
312             assert(ptr != NULL);\r
313             matVec.push_back(ptr);\r
314         }\r
315     }\r
316 \r
317     ~BytomMatList16() {\r
318         for(int i = 0; i < 256; i++)\r
319             delete matVec[i];\r
320     }\r
321 \r
322     void init(const Words32& X_in) {\r
323         Words32 X = X_in;\r
324         LTCMemory ltcMem;\r
325         for(int i = 0; i < 128; i++) {\r
326             ltcMem.scrypt(X);\r
327             matVec[2*i]->copyFromEven(ltcMem);\r
328             matVec[2*i + 1]->copyFromOdd(ltcMem);\r
329         }\r
330     }\r
331 \r
332     // void copyFrom(BytomMatList8& other) {\r
333     //     for(int i=0; i<256; i++) {\r
334     //         matVec[i]->copyFrom(*other.matVec[i]);\r
335     //     }\r
336     // }\r
337 \r
338     // void copyFrom(BytomMatList16& other) {\r
339     //     for(int i=0; i<256; i++) {\r
340     //         matVec[i]->copyFrom(*other.matVec[i]);\r
341     //     }\r
342     // }\r
343 };\r
344 \r
345 // extern BytomMatList8* matList_int8;\r
346 extern BytomMatList16* matList_int16;\r
347 \r
348 inline void iter_mineBytom(const uint8_t *fixedMessage,\r
349                             uint32_t len,\r
350                             // uint8_t nonce[8],\r
351                             uint8_t result[32]) {\r
352     Mat256x256i8 *resArr8 = new Mat256x256i8[4];\r
353 \r
354     clock_t start, end;\r
355     start = clock();\r
356     // Itz faster using single thread ...\r
357     #pragma omp parallel for simd\r
358     for(int k = 0; k < 4; k++) { // The k-loop\r
359         sha3_ctx *ctx = new sha3_ctx;\r
360         Mat256x256i16 *mat16 = new Mat256x256i16;\r
361         Mat256x256i16 *tmp16 = new Mat256x256i16;\r
362         uint8_t sequence[32];\r
363         rhash_sha3_256_init(ctx);\r
364         rhash_sha3_update(ctx, fixedMessage + (len*k/4), len/4);//分四轮消耗掉fixedMessage\r
365         rhash_sha3_final(ctx, sequence);\r
366         tmp16->toIdentityMatrix();\r
367 \r
368         for(int j = 0; j < 2; j++) {\r
369             // equivalent as tmp=tmp*matlist, i+=1 \r
370             for(int i = 0; i < 32; i += 2) {\r
371                 // "mc = ma dot mb.T" in GoLang code\r
372                 mat16->mul(*tmp16, matList_int16->at(sequence[i]));\r
373                 // "ma = mc" in GoLang code\r
374                 tmp16->mul(*mat16, matList_int16->at(sequence[i+1]));\r
375             }\r
376         }\r
377         // "res[k] = mc" in GoLang code\r
378         tmp16->toMatI8(resArr8[k]); // 0.00018s\r
379         delete mat16;\r
380         delete tmp16;\r
381         delete ctx;\r
382     }\r
383 \r
384     // 3.7e-05s\r
385     Mat256x256i8 *res8 = new Mat256x256i8;\r
386     res8->add(resArr8[0], resArr8[1]);\r
387     res8->add(*res8, resArr8[2]);\r
388     res8->add(*res8, resArr8[3]);\r
389 \r
390     end = clock();    \r
391     // std::cout << "\tTime for getting MulMatix: "\r
392     //           << (double)(end - start) / CLOCKS_PER_SEC * 1000 << "ms"\r
393     //           << std::endl;\r
394 \r
395     Arr256x64i32 arr(*res8);\r
396     arr.reduceFNV();\r
397     sha3_ctx *ctx = new sha3_ctx;\r
398     rhash_sha3_256_init(ctx);\r
399     rhash_sha3_update(ctx, arr.d0RawPtr(), 256);\r
400     rhash_sha3_final(ctx, result);\r
401 \r
402     delete res8;\r
403     delete[] resArr8;\r
404     delete ctx;\r
405 }\r
406 \r
407 inline void incrNonce(uint8_t nonce[8]) {\r
408     for(int i = 0; i < 8; i++) {\r
409         if(nonce[i] != 255) {\r
410             nonce[i]++;\r
411             break;\r
412         } else {\r
413             nonce[i] = 0;\r
414         }\r
415     }\r
416 }\r
417 \r
418 inline int countLeadingZero(uint8_t result[32]) {\r
419     int count = 0;\r
420     for(int i = 31; i >= 0; i--) { // NOTE: reverse\r
421         if(result[i] < 1) {\r
422             count += 8;\r
423         } else if(result[i]<2)  {\r
424             count += 7;\r
425             break;\r
426         } else if(result[i]<4)  {\r
427             count += 6;\r
428             break;\r
429         } else if(result[i]<8)  {\r
430             count += 5;\r
431             break;\r
432         } else if(result[i]<16) {\r
433             count += 4;\r
434             break;\r
435         } else if(result[i]<32) {\r
436             count += 3;\r
437             break;\r
438         } else if(result[i]<64) {\r
439             count += 2;\r
440             break;\r
441         } else if(result[i]<128) {\r
442             count += 1;\r
443             break;\r
444         }\r
445     }\r
446     return count;\r
447 }\r
448 \r
449 // inline int test_mineBytom(\r
450 //     const uint8_t *fixedMessage,\r
451 //     uint32_t len,\r
452 //     uint8_t nonce[32],\r
453 //     int count,\r
454 //     int leadingZeroThres)\r
455 // {\r
456 //   assert(len%4==0);\r
457 //   int step;\r
458 //   for(step=0; step<count; step++) {\r
459 //     uint8_t result[32];\r
460 //     //std::cerr<<"Mine step "<<step<<std::endl;\r
461 //     iter_mineBytom(fixedMessage,100,nonce,result);\r
462 //     std::cerr<<"Mine step "<<step<<std::endl;\r
463 //     for (int i = 0; i < 32; i++) {\r
464 //       printf("%02x ", result[i]);\r
465 //       if (i % 8 == 7)\r
466 //         printf("\n");\r
467 //     }\r
468 //     if (countLeadingZero(result) > leadingZeroThres)\r
469 //       return step;\r
470 //     incrNonce(nonce);\r
471 //   }\r
472 //   return step;\r
473 // }\r
474 \r
475 \r
476 #endif\r
477 \r