]> Git Repo - cpuminer-multi.git/blame - algo/x11evo.c
rainforest: optimize rf_ctx organization for better cache locality
[cpuminer-multi.git] / algo / x11evo.c
CommitLineData
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
24enum 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
39static void swap8(uint8_t *a, uint8_t *b)
40{
41 uint8_t t = *a;
42 *a = *b;
43 *b = t;
44}
45
46static void initPerm(uint8_t n[], int count)
47{
48 for (int i = 0; i < count; i++)
49 n[i] = i;
50}
51
52static 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
73static 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
95static __thread uint32_t s_ntime = 0;
96static char hashOrder[HASH_FUNC_COUNT + 1] = { 0 };
97static int s_sequence = -1;
98
99#define INITIAL_DATE 0x57254700
100static 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
106static 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
115void 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
215int 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}
This page took 0.051522 seconds and 4 git commands to generate.