Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/algo/quark.c
1201 views
1
#include "miner.h"
2
3
#include <string.h>
4
#include <stdint.h>
5
6
#include "sha3/sph_blake.h"
7
#include "sha3/sph_bmw.h"
8
#include "sha3/sph_groestl.h"
9
#include "sha3/sph_jh.h"
10
#include "sha3/sph_keccak.h"
11
#include "sha3/sph_skein.h"
12
13
/* Move init out of loop, so init once externally,
14
and then use one single memcpy with that bigger memory block */
15
typedef struct {
16
sph_blake512_context blake1, blake2;
17
sph_bmw512_context bmw1, bmw2;
18
sph_groestl512_context groestl1, groestl2;
19
sph_skein512_context skein1, skein2;
20
sph_jh512_context jh1, jh2;
21
sph_keccak512_context keccak1, keccak2;
22
bool init_done;
23
} quarkhash_context_holder;
24
25
static quarkhash_context_holder _ALIGN(128) cached_ctx;
26
27
void init_quarkhash_contexts()
28
{
29
sph_blake512_init(&cached_ctx.blake1);
30
sph_bmw512_init(&cached_ctx.bmw1);
31
sph_groestl512_init(&cached_ctx.groestl1);
32
sph_skein512_init(&cached_ctx.skein1);
33
sph_groestl512_init(&cached_ctx.groestl2);
34
sph_jh512_init(&cached_ctx.jh1);
35
sph_blake512_init(&cached_ctx.blake2);
36
sph_bmw512_init(&cached_ctx.bmw2);
37
sph_keccak512_init(&cached_ctx.keccak1);
38
sph_skein512_init(&cached_ctx.skein2);
39
sph_keccak512_init(&cached_ctx.keccak2);
40
sph_jh512_init(&cached_ctx.jh2);
41
cached_ctx.init_done = true;
42
}
43
44
void quarkhash(void *state, const void *input)
45
{
46
uint32_t _ALIGN(128) hash[16];
47
quarkhash_context_holder _ALIGN(128) ctx;
48
uint32_t mask = 8;
49
50
if (cached_ctx.init_done)
51
memcpy(&ctx, &cached_ctx, sizeof(cached_ctx));
52
else {
53
applog(LOG_ERR, "Attempt to hash quark without init!");
54
exit(1);
55
}
56
57
sph_blake512 (&ctx.blake1, input, 80);
58
sph_blake512_close (&ctx.blake1, hash); //0
59
60
sph_bmw512 (&ctx.bmw1, hash, 64);
61
sph_bmw512_close(&ctx.bmw1, hash); //1
62
63
if (hash[0] & mask) {
64
sph_groestl512 (&ctx.groestl1, hash, 64);
65
sph_groestl512_close(&ctx.groestl1, hash); //2
66
} else {
67
sph_skein512 (&ctx.skein1, hash, 64);
68
sph_skein512_close(&ctx.skein1, hash); //2
69
}
70
71
sph_groestl512 (&ctx.groestl2, hash, 64);
72
sph_groestl512_close(&ctx.groestl2, hash); //3
73
74
sph_jh512 (&ctx.jh1, hash, 64);
75
sph_jh512_close(&ctx.jh1, hash); //4
76
77
if (hash[0] & mask) {
78
sph_blake512 (&ctx.blake2, hash, 64);
79
sph_blake512_close(&ctx.blake2, hash); //5
80
} else {
81
sph_bmw512 (&ctx.bmw2, hash, 64);
82
sph_bmw512_close(&ctx.bmw2, hash); //5
83
}
84
85
sph_keccak512 (&ctx.keccak1, hash, 64);
86
sph_keccak512_close(&ctx.keccak1, hash); //6
87
88
sph_skein512 (&ctx.skein2, hash, 64);
89
sph_skein512_close(&ctx.skein2, hash); //7
90
91
if (hash[0] & mask) {
92
sph_keccak512 (&ctx.keccak2, hash, 64);
93
sph_keccak512_close(&ctx.keccak2, hash); //8
94
} else {
95
sph_jh512 (&ctx.jh2, hash, 64);
96
sph_jh512_close(&ctx.jh2, hash); //8
97
}
98
99
memcpy(state, hash, 32);
100
}
101
102
int scanhash_quark(int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done)
103
{
104
uint32_t _ALIGN(128) hash32[8];
105
uint32_t _ALIGN(128) endiandata[20];
106
uint32_t *pdata = work->data;
107
uint32_t *ptarget = work->target;
108
109
const uint32_t Htarg = ptarget[7];
110
const uint32_t first_nonce = pdata[19];
111
112
uint32_t n = first_nonce;
113
114
for (int i=0; i < 19; i++) {
115
be32enc(&endiandata[i], pdata[i]);
116
}
117
118
do {
119
be32enc(&endiandata[19], n);
120
quarkhash(hash32, endiandata);
121
if (hash32[7] < Htarg && fulltest(hash32, ptarget)) {
122
work_set_target_ratio(work, hash32);
123
*hashes_done = n - first_nonce + 1;
124
pdata[19] = n;
125
return true;
126
}
127
n++;
128
129
} while (n < max_nonce && !work_restart[thr_id].restart);
130
131
*hashes_done = n - first_nonce + 1;
132
pdata[19] = n;
133
134
return 0;
135
}
136
137