Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/algo/x11evo.c
1201 views
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
}
257
258