]>
Commit | Line | Data |
---|---|---|
22dd788c TP |
1 | /** |
2 | * X11EVO algo implementation | |
3 | * | |
4 | * Trivial implementation by tpruvot@github May 2016 | |
5 | */ | |
6 | #include "miner.h" | |
7 | ||
8 | #include <stdio.h> | |
9 | #include <stdlib.h> | |
10 | #include <string.h> | |
11 | ||
12 | #include <sha3/sph_blake.h> | |
13 | #include <sha3/sph_bmw.h> | |
14 | #include <sha3/sph_groestl.h> | |
15 | #include <sha3/sph_jh.h> | |
16 | #include <sha3/sph_keccak.h> | |
17 | #include <sha3/sph_skein.h> | |
18 | #include <sha3/sph_luffa.h> | |
19 | #include <sha3/sph_cubehash.h> | |
20 | #include <sha3/sph_shavite.h> | |
21 | #include <sha3/sph_simd.h> | |
22 | #include <sha3/sph_echo.h> | |
23 | ||
24 | enum Algo { | |
25 | BLAKE = 0, | |
26 | BMW, | |
27 | GROESTL, | |
28 | SKEIN, | |
29 | JH, | |
30 | KECCAK, | |
31 | LUFFA, | |
32 | CUBEHASH, | |
33 | SHAVITE, | |
34 | SIMD, | |
35 | ECHO, | |
36 | HASH_FUNC_COUNT | |
37 | }; | |
38 | ||
39 | static void swap8(uint8_t *a, uint8_t *b) | |
40 | { | |
41 | uint8_t t = *a; | |
42 | *a = *b; | |
43 | *b = t; | |
44 | } | |
45 | ||
46 | static void initPerm(uint8_t n[], int count) | |
47 | { | |
48 | for (int i = 0; i < count; i++) | |
49 | n[i] = i; | |
50 | } | |
51 | ||
52 | static int nextPerm(uint8_t n[], int count) | |
53 | { | |
54 | int tail, i, j; | |
55 | ||
56 | if (count <= 1) | |
57 | return 0; | |
58 | ||
59 | for (i = count - 1; i>0 && n[i - 1] >= n[i]; i--); | |
60 | tail = i; | |
61 | ||
62 | if (tail > 0) { | |
63 | for (j = count - 1; j>tail && n[j] <= n[tail - 1]; j--); | |
64 | swap8(&n[tail - 1], &n[j]); | |
65 | } | |
66 | ||
67 | for (i = tail, j = count - 1; i<j; i++, j--) | |
68 | swap8(&n[i], &n[j]); | |
69 | ||
70 | return (tail != 0); | |
71 | } | |
72 | ||
73 | static void getAlgoString(char *str, int seq) | |
74 | { | |
75 | uint8_t algoList[HASH_FUNC_COUNT]; | |
76 | char *sptr; | |
77 | ||
78 | initPerm(algoList, HASH_FUNC_COUNT); | |
79 | ||
80 | for (int k = 0; k < seq; k++) { | |
81 | nextPerm(algoList, HASH_FUNC_COUNT); | |
82 | } | |
83 | ||
84 | sptr = str; | |
85 | for (int j = 0; j < HASH_FUNC_COUNT; j++) { | |
86 | if (algoList[j] >= 10) | |
87 | sprintf(sptr, "%c", 'A' + (algoList[j] - 10)); | |
88 | else | |
89 | sprintf(sptr, "%u", (uint32_t) algoList[j]); | |
90 | sptr++; | |
91 | } | |
92 | *sptr = '\0'; | |
93 | } | |
94 | ||
95 | static __thread uint32_t s_ntime = 0; | |
96 | static char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; | |
97 | static int s_sequence = -1; | |
98 | ||
99 | #define INITIAL_DATE 0x57254700 | |
100 | static inline int getCurrentAlgoSeq(uint32_t current_time) | |
101 | { | |
102 | // change once per day | |
103 | return (int) (current_time - INITIAL_DATE) / (60 * 60 * 24); | |
104 | } | |
105 | ||
106 | static void evo_twisted_code(uint32_t ntime, char *permstr) | |
107 | { | |
108 | int seq = getCurrentAlgoSeq(ntime); | |
109 | if (s_sequence != seq) { | |
110 | getAlgoString(permstr, seq); | |
111 | s_sequence = seq; | |
112 | } | |
113 | } | |
114 | ||
115 | void x11evo_hash(void *output, const void *input) | |
116 | { | |
117 | uint32_t hash[64/4]; | |
118 | uint32_t len = 80; | |
119 | ||
120 | sph_blake512_context ctx_blake; | |
121 | sph_bmw512_context ctx_bmw; | |
122 | sph_groestl512_context ctx_groestl; | |
123 | sph_skein512_context ctx_skein; | |
124 | sph_jh512_context ctx_jh; | |
125 | sph_keccak512_context ctx_keccak; | |
126 | sph_luffa512_context ctx_luffa1; | |
127 | sph_cubehash512_context ctx_cubehash1; | |
128 | sph_shavite512_context ctx_shavite1; | |
129 | sph_simd512_context ctx_simd1; | |
130 | sph_echo512_context ctx_echo1; | |
131 | ||
132 | if (s_sequence == -1) { | |
133 | uint32_t *data = (uint32_t*) input; | |
134 | const uint32_t ntime = data[17]; | |
135 | evo_twisted_code(ntime, hashOrder); | |
136 | } | |
137 | ||
138 | void *in = (void*) input; | |
139 | int size = len; | |
140 | ||
141 | const int hashes = (int) strlen(hashOrder); | |
142 | ||
143 | for (int i = 0; i < hashes; i++) | |
144 | { | |
145 | const char elem = hashOrder[i]; | |
146 | uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; | |
147 | ||
148 | if (i > 0) { | |
149 | in = (void*) hash; | |
150 | size = 64; | |
151 | } | |
152 | ||
153 | switch (algo) { | |
154 | case BLAKE: | |
155 | sph_blake512_init(&ctx_blake); | |
156 | sph_blake512 (&ctx_blake, in, size); | |
157 | sph_blake512_close (&ctx_blake, hash); | |
158 | break; | |
159 | case BMW: | |
160 | sph_bmw512_init(&ctx_bmw); | |
161 | sph_bmw512 (&ctx_bmw, in, size); | |
162 | sph_bmw512_close(&ctx_bmw, hash); | |
163 | break; | |
164 | case GROESTL: | |
165 | sph_groestl512_init(&ctx_groestl); | |
166 | sph_groestl512 (&ctx_groestl, in, size); | |
167 | sph_groestl512_close(&ctx_groestl, hash); | |
168 | break; | |
169 | case SKEIN: | |
170 | sph_skein512_init(&ctx_skein); | |
171 | sph_skein512 (&ctx_skein, in, size); | |
172 | sph_skein512_close (&ctx_skein, hash); | |
173 | break; | |
174 | case JH: | |
175 | sph_jh512_init(&ctx_jh); | |
176 | sph_jh512 (&ctx_jh, in, size); | |
177 | sph_jh512_close(&ctx_jh, hash); | |
178 | break; | |
179 | case KECCAK: | |
180 | sph_keccak512_init(&ctx_keccak); | |
181 | sph_keccak512 (&ctx_keccak, in, size); | |
182 | sph_keccak512_close(&ctx_keccak, hash); | |
183 | break; | |
184 | case LUFFA: | |
185 | sph_luffa512_init (&ctx_luffa1); | |
186 | sph_luffa512 (&ctx_luffa1, in, size); | |
187 | sph_luffa512_close (&ctx_luffa1, hash); | |
188 | break; | |
189 | case CUBEHASH: | |
190 | sph_cubehash512_init (&ctx_cubehash1); | |
191 | sph_cubehash512 (&ctx_cubehash1, in, size); | |
192 | sph_cubehash512_close(&ctx_cubehash1, hash); | |
193 | break; | |
194 | case SHAVITE: | |
195 | sph_shavite512_init (&ctx_shavite1); | |
196 | sph_shavite512 (&ctx_shavite1, in, size); | |
197 | sph_shavite512_close(&ctx_shavite1, hash); | |
198 | break; | |
199 | case SIMD: | |
200 | sph_simd512_init (&ctx_simd1); | |
201 | sph_simd512 (&ctx_simd1, in, size); | |
202 | sph_simd512_close(&ctx_simd1, hash); | |
203 | break; | |
204 | case ECHO: | |
205 | sph_echo512_init (&ctx_echo1); | |
206 | sph_echo512 (&ctx_echo1, in, size); | |
207 | sph_echo512_close(&ctx_echo1, hash); | |
208 | break; | |
209 | } | |
210 | } | |
211 | ||
212 | memcpy(output, hash, 32); | |
213 | } | |
214 | ||
215 | int scanhash_x11evo(int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done) | |
216 | { | |
217 | uint32_t _ALIGN(128) hash32[8]; | |
218 | uint32_t _ALIGN(128) endiandata[20]; | |
219 | uint32_t *pdata = work->data; | |
220 | uint32_t *ptarget = work->target; | |
221 | const uint32_t Htarg = ptarget[7]; | |
222 | const uint32_t first_nonce = pdata[19]; | |
223 | uint32_t nonce = first_nonce; | |
224 | volatile uint8_t *restart = &(work_restart[thr_id].restart); | |
225 | ||
226 | if (s_ntime != pdata[17] || s_sequence == -1) { | |
227 | uint32_t ntime = swab32(pdata[17]); | |
228 | evo_twisted_code(ntime, hashOrder); | |
229 | s_ntime = ntime; | |
230 | if (opt_debug) applog(LOG_DEBUG, "evo hash order %s (%08x)", hashOrder, ntime); | |
231 | } | |
232 | ||
233 | if (opt_benchmark) | |
234 | ptarget[7] = 0x0cff; | |
235 | ||
236 | for (int k=0; k < 19; k++) | |
237 | be32enc(&endiandata[k], pdata[k]); | |
238 | ||
239 | do { | |
240 | be32enc(&endiandata[19], nonce); | |
241 | x11evo_hash(hash32, endiandata); | |
242 | ||
243 | if (hash32[7] <= Htarg && fulltest(hash32, ptarget)) { | |
244 | work_set_target_ratio(work, hash32); | |
245 | pdata[19] = nonce; | |
246 | *hashes_done = pdata[19] - first_nonce; | |
247 | return 1; | |
248 | } | |
249 | nonce++; | |
250 | ||
251 | } while (nonce < max_nonce && !(*restart)); | |
252 | ||
253 | pdata[19] = nonce; | |
254 | *hashes_done = pdata[19] - first_nonce + 1; | |
255 | return 0; | |
256 | } |