Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/algo/timetravel.c
1201 views
1
#include <miner.h>
2
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <string.h>
6
#include <stdio.h>
7
8
#include <sha3/sph_blake.h>
9
#include <sha3/sph_bmw.h>
10
#include <sha3/sph_groestl.h>
11
#include <sha3/sph_jh.h>
12
#include <sha3/sph_keccak.h>
13
#include <sha3/sph_skein.h>
14
#include <sha3/sph_luffa.h>
15
#include <sha3/sph_cubehash.h>
16
17
// Machinecoin Genesis Timestamp
18
#define HASH_FUNC_BASE_TIMESTAMP 1389040865
19
20
#define HASH_FUNC_COUNT 8
21
#define HASH_FUNC_COUNT_PERMUTATIONS 40320
22
23
static __thread uint32_t s_ntime = UINT32_MAX;
24
static __thread int permutation[HASH_FUNC_COUNT] = { 0 };
25
26
// helpers
27
static void swap(int *a, int *b) {
28
int c = *a;
29
*a = *b;
30
*b = c;
31
}
32
33
static void reverse(int *pbegin, int *pend) {
34
while ( (pbegin != pend) && (pbegin != --pend) )
35
swap(pbegin++, pend);
36
}
37
38
static void next_permutation(int *pbegin, int *pend) {
39
if (pbegin == pend)
40
return;
41
42
int *i = pbegin;
43
++i;
44
if (i == pend)
45
return;
46
47
i = pend;
48
--i;
49
50
while (1) {
51
int *j = i;
52
--i;
53
54
if (*i < *j) {
55
int *k = pend;
56
57
while (!(*i < *--k))
58
/* pass */;
59
60
swap(i, k);
61
reverse(j, pend);
62
return; // true
63
}
64
65
if (i == pbegin) {
66
reverse(pbegin, pend);
67
return; // false
68
}
69
}
70
}
71
72
void timetravel_hash(void *output, const void *input)
73
{
74
uint32_t _ALIGN(64) hash[16 * HASH_FUNC_COUNT];
75
uint32_t *hashA, *hashB;
76
uint32_t dataLen = 64;
77
uint32_t *work_data = (uint32_t *)input;
78
const uint32_t timestamp = work_data[17];
79
80
sph_blake512_context ctx_blake;
81
sph_bmw512_context ctx_bmw;
82
sph_groestl512_context ctx_groestl;
83
sph_skein512_context ctx_skein;
84
sph_jh512_context ctx_jh;
85
sph_keccak512_context ctx_keccak;
86
sph_luffa512_context ctx_luffa;
87
sph_cubehash512_context ctx_cubehash;
88
89
// We want to permute algorithms. To get started we
90
// initialize an array with a sorted sequence of unique
91
// integers where every integer represents its own algorithm.
92
if (timestamp != s_ntime) {
93
int steps = (int) (timestamp - HASH_FUNC_BASE_TIMESTAMP) % HASH_FUNC_COUNT_PERMUTATIONS;
94
for (int i = 0; i < HASH_FUNC_COUNT; i++) {
95
permutation[i] = i;
96
}
97
for (int i = 0; i < steps; i++) {
98
next_permutation(permutation, permutation + HASH_FUNC_COUNT);
99
}
100
s_ntime = timestamp;
101
}
102
103
for (int i = 0; i < HASH_FUNC_COUNT; i++) {
104
if (i == 0) {
105
dataLen = 80;
106
hashA = work_data;
107
} else {
108
dataLen = 64;
109
hashA = &hash[16 * (i - 1)];
110
}
111
hashB = &hash[16 * i];
112
113
switch(permutation[i]) {
114
case 0:
115
sph_blake512_init(&ctx_blake);
116
sph_blake512(&ctx_blake, hashA, dataLen);
117
sph_blake512_close(&ctx_blake, hashB);
118
break;
119
case 1:
120
sph_bmw512_init(&ctx_bmw);
121
sph_bmw512 (&ctx_bmw, hashA, dataLen);
122
sph_bmw512_close(&ctx_bmw, hashB);
123
break;
124
case 2:
125
sph_groestl512_init(&ctx_groestl);
126
sph_groestl512 (&ctx_groestl, hashA, dataLen);
127
sph_groestl512_close(&ctx_groestl, hashB);
128
break;
129
case 3:
130
sph_skein512_init(&ctx_skein);
131
sph_skein512 (&ctx_skein, hashA, dataLen);
132
sph_skein512_close(&ctx_skein, hashB);
133
break;
134
case 4:
135
sph_jh512_init(&ctx_jh);
136
sph_jh512 (&ctx_jh, hashA, dataLen);
137
sph_jh512_close(&ctx_jh, hashB);
138
break;
139
case 5:
140
sph_keccak512_init(&ctx_keccak);
141
sph_keccak512 (&ctx_keccak, hashA, dataLen);
142
sph_keccak512_close(&ctx_keccak, hashB);
143
break;
144
case 6:
145
sph_luffa512_init(&ctx_luffa);
146
sph_luffa512 (&ctx_luffa, hashA, dataLen);
147
sph_luffa512_close(&ctx_luffa, hashB);
148
break;
149
case 7:
150
sph_cubehash512_init(&ctx_cubehash);
151
sph_cubehash512 (&ctx_cubehash, hashA, dataLen);
152
sph_cubehash512_close(&ctx_cubehash, hashB);
153
break;
154
default:
155
break;
156
}
157
}
158
159
memcpy(output, &hash[16 * (HASH_FUNC_COUNT - 1)], 32);
160
}
161
162
int scanhash_timetravel(int thr_id, struct work *work, uint32_t max_nonce, uint64_t *hashes_done)
163
{
164
uint32_t _ALIGN(64) hash[8];
165
uint32_t _ALIGN(64) endiandata[20];
166
uint32_t *pdata = work->data;
167
uint32_t *ptarget = work->target;
168
169
const uint32_t Htarg = ptarget[7];
170
const uint32_t first_nonce = pdata[19];
171
uint32_t nonce = first_nonce;
172
volatile uint8_t *restart = &(work_restart[thr_id].restart);
173
174
if (opt_benchmark)
175
ptarget[7] = 0x0cff;
176
177
for (int k=0; k < 19; k++)
178
be32enc(&endiandata[k], pdata[k]);
179
180
do {
181
be32enc(&endiandata[19], nonce);
182
timetravel_hash(hash, endiandata);
183
184
if (hash[7] <= Htarg && fulltest(hash, ptarget)) {
185
work_set_target_ratio(work, hash);
186
pdata[19] = nonce;
187
*hashes_done = pdata[19] - first_nonce;
188
return 1;
189
}
190
nonce++;
191
192
} while (nonce < max_nonce && !(*restart));
193
194
pdata[19] = nonce;
195
*hashes_done = pdata[19] - first_nonce + 1;
196
return 0;
197
}
198
199