-
Notifications
You must be signed in to change notification settings - Fork 4
/
algo-gate-api.h
325 lines (253 loc) · 11.8 KB
/
algo-gate-api.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#ifndef ALGO_GATE_API_
#define ALGO_GATE_API_
#include "miner.h"
#include "simd-utils.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/////////////////////////////
////
//// NEW FEATURE: algo_gate
////
//// algos define targets for their common functions
//// and define a function for miner-thread to call to register
//// their targets. miner thread builds the gate, and array of structs
//// of function pointers, by calling each algo's register function.
//
//
//
// So you want to add an algo. Well it is a little easier now.
// Look at existing algos for guidance.
//
// 1. Define the algo, miner.h, previously in cpu-miner.c
//
// 2.Define custom versions of the mandatory function for the new algo.
//
// 3. Next look through the list of unsafe functions to determine
// if any apply to the new algo. If so they must also be defined.
//
// 4. Look through the list of safe functions to see if any apply
// to the new algo. If so look at the null instance of the function
// to see if it satisfies its needs.
//
// 5. If any of the default safe functions are not fit for the new algo
// a custom function will have to be defined.
//
// 6. Determine if other non existant functions are required.
// That is determined by the need to add code in cpu-miner.c
// that applies only to the new algo. That is forbidden. All
// algo specific code must be in the algo's file.
//
// 7. If new functions need to be added to the gate add the type
// to the structure, declare a null instance in this file and define
// it in algo-gate-api.c. It must be a safe optional function so the null
// instance must return a success code and otherwise do nothing.
//
// 8. When all the custom functions are defined write a registration
// function to initialze the gate's function pointers with the custom
// functions. It is not necessary to initialze safe optional null
// instances as they are defined by default, or unsafe functions that
// are not needed by the algo.
//
// 9. Add a case entry to the switch/case in function register_gate
// in file algo-gate-api.c for the new algo.
//
// 10 If a new function type was defined add an entry to init algo_gate
// to initialize the new function to its null instance described in step 7.
//
// 11. If the new algo has aliases add them to the alias array in
// algo-gate-api.c
//
// 12. Include algo-gate-api.h and miner.h inthe algo's source file.
//
// 13. Inlude any other algo source files required by the new algo.
//
// 14. Done, compile and run.
// declare some function pointers
// mandatory functions require a custom function specific to the algo
// be defined.
// otherwise the null instance will return a fail code.
// Optional functions may not be required for certain algos or the null
// instance provides a safe default. If the default is suitable for
// an algo it is not necessary to define a custom function.
//
// my hack at creating a set data type using bit masks. Set inclusion,
// exclusion union and intersection operations are provided for convenience. In
// // some cases it may be desireable to use boolean algebra directly on the
// data to perform set operations. Sets can be represented as single
// elements, a bitwise OR of multiple elements, a bitwise OR of multiple
// set variables or constants, or combinations of the above.
// Examples:
//
// my_set = set_element;
// another_set = my_set | another_set_element;
typedef uint32_t set_t;
#define EMPTY_SET 0
#define SSE2_OPT 1
#define AES_OPT 2
#define SSE42_OPT 4
#define AVX_OPT 8 // Sandybridge
#define AVX2_OPT 0x10 // Haswell, Zen1
#define SHA_OPT 0x20 // Zen1, Icelake (sha256)
#define AVX512_OPT 0x40 // Skylake-X (AVX512[F,VL,DQ,BW])
#define VAES_OPT 0x80 // Icelake (VAES & AVX512)
#define VAES256_OPT 0x100 // Zen3 (VAES without AVX512)
// return set containing all elements from sets a & b
inline set_t set_union(set_t a, set_t b) { return a | b; }
// return set contained common elements from sets a & b
inline set_t set_intsec(set_t a, set_t b) { return a & b; }
// all elements in set a are included in set b
__attribute__((always_inline)) inline bool set_incl(set_t a, set_t b) {
return (a & b) == a;
}
// no elements in set a are included in set b
inline bool set_excl(set_t a, set_t b) { return (a & b) == 0; }
typedef struct {
// Mandatory functions, one of these is mandatory. If a generic scanhash
// is used a custom target hash function must be registered, with a custom
// scanhash the target hash function can be called directly and doesn't need
// to be registered with the gate.
int (*scanhash)(struct work *, uint32_t, uint64_t *, struct thr_info *);
int (*hash)(void *, const void *, int);
// optional, safe to use default in most cases
// Called once by each miner thread to allocate thread local buffers and
// other initialization specific to miner threads.
bool (*miner_thread_init)(int);
// Get thread local copy of blockheader with unique nonce.
void (*get_new_work)(struct work *, struct work *, int, uint32_t *);
// Decode getwork blockheader
bool (*work_decode)(struct work *);
// Extra getwork data
void (*decode_extra_data)(struct work *, uint64_t *);
bool (*submit_getwork_result)(CURL *, struct work *);
void (*gen_merkle_root)(char *, struct stratum_ctx *);
// Increment extranonce
void (*build_extraheader)(struct work *, struct stratum_ctx *);
void (*build_block_header)(struct work *, uint32_t, uint32_t *, uint32_t *,
uint32_t, uint32_t, unsigned char *);
// Build mining.submit message
void (*build_stratum_request)(char *, struct work *, struct stratum_ctx *);
char *(*malloc_txs_request)(struct work *);
// Big endian or little endian
void (*set_work_data_endian)(struct work *);
double (*calc_network_diff)(struct work *);
// Wait for first work
bool (*ready_to_mine)(struct work *, struct stratum_ctx *, int);
// Diverge mining threads
bool (*do_this_thread)(int);
// After do_this_thread
void (*resync_threads)(int, struct work *);
// No longer needed
json_t *(*longpoll_rpc_call)(CURL *, int *, char *);
set_t optimizations;
int (*get_work_data_size)();
int ntime_index;
int nbits_index;
int nonce_index; // use with caution, see warning below
int work_cmp_size;
} algo_gate_t;
extern algo_gate_t algo_gate;
// Declare generic null targets, default for many gate functions
// Functions that use one of these generic targets do not have
// a default defined below. Some algos may override a defined default
// with a generic.
void do_nothing();
bool return_true();
bool return_false();
void *return_null();
void algo_not_tested();
void algo_not_implemented();
void four_way_not_tested();
// Warning: algo_gate.nonce_index should only be used in targetted code
// due to different behaviours by different targets. The JR2 index uses an
// 8 bit offset while all others user 32 bit offset. c/c++ pointer arithmetic
// conventions results in different behaviour for pointers with different
// target sizes requiring customized casting to make it work consistently.
// Rant mode: yet another thing I hate about c/c++. Array indexes should
// be scaled, pointer offsets should always be bytes. No confusion and no
// hidden math.
#define STD_NTIME_INDEX 17
#define STD_NBITS_INDEX 18
#define STD_NONCE_INDEX 19 // 32 bit offset
#define STD_WORK_DATA_SIZE 128
#define STD_WORK_CMP_SIZE 76
//#define JR2_NONCE_INDEX 39 // 8 bit offset
// These indexes are only used with JSON RPC2 and are not gated.
//#define JR2_WORK_CMP_INDEX_2 43
//#define JR2_WORK_CMP_SIZE_2 33
// deprecated, use generic instead
int null_scanhash();
// Default generic, may be used in many cases.
// N-way is more complicated, requires many different implementations
// depending on architecture, input format, and output format.
// Naming convention is scanhash_[N]way_[input format]in_[output format]out
// N = number of lanes
// input/output format:
// 32: 32 bit interleaved parallel lanes
// 64: 64 bit interleaved parallel lanes
// 640: input only, not interleaved, contiguous serial 640 bit lanes.
// 256: output only, not interleaved, contiguous serial 256 bit lanes.
int scanhash_generic(struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr);
#if defined(__AVX2__)
// int scanhash_4way_64in_64out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
// int scanhash_4way_64in_256out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
int scanhash_4way_64in_32out(struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr);
// int scanhash_8way_32in_32out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
#endif
#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512DQ__) && \
defined(__AVX512BW__)
// int scanhash_8way_64in_64out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
// int scanhash_8way_64in_256out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
int scanhash_8way_64in_32out(struct work *work, uint32_t max_nonce,
uint64_t *hashes_done, struct thr_info *mythr);
// int scanhash_16way_32in_32out( struct work *work, uint32_t max_nonce,
// uint64_t *hashes_done, struct thr_info *mythr );
#endif
// displays warning
int null_hash();
// optional safe targets, default listed first unless noted.
void std_get_new_work(struct work *work, struct work *g_work, int thr_id,
uint32_t *end_nonce_ptr);
void sha256d_gen_merkle_root(char *merkle_root, struct stratum_ctx *sctx);
void SHA256_gen_merkle_root(char *merkle_root, struct stratum_ctx *sctx);
bool std_le_work_decode(struct work *work);
bool std_be_work_decode(struct work *work);
bool std_le_submit_getwork_result(CURL *curl, struct work *work);
bool std_be_submit_getwork_result(CURL *curl, struct work *work);
void std_le_build_stratum_request(char *req, struct work *work);
void std_be_build_stratum_request(char *req, struct work *work);
char *std_malloc_txs_request(struct work *work);
// Default is do_nothing, little endian is assumed
void set_work_data_big_endian(struct work *work);
double std_calc_network_diff(struct work *work);
void std_build_block_header(struct work *g_work, uint32_t version,
uint32_t *prevhash, uint32_t *merkle_root,
uint32_t ntime, uint32_t nbits,
unsigned char *final_sapling_hash);
void std_build_extraheader(struct work *work, struct stratum_ctx *sctx);
json_t *std_longpoll_rpc_call(CURL *curl, int *err, char *lp_url);
bool std_ready_to_mine(struct work *work, struct stratum_ctx *stratum,
int thr_id);
int std_get_work_data_size();
// Gate admin functions
// Called from main to initialize all gate functions and algo-specific data
// by calling the algo's register function.
bool register_algo_gate(int algo, algo_gate_t *gate);
// Called by algos to verride any default gate functions that are applicable
// and do any other algo-specific initialization.
// The register functions for all the algos can be declared here to reduce
// compiler warnings but that's just more work for devs adding new algos.
bool register_algo(algo_gate_t *gate);
// use this to call the hash function of an algo directly, ie util.c test.
void exec_hash_function(int algo, void *output, const void *pdata);
// Validate a string as a known algo and alias, updates arg to proper
// algo name if valid alias, NULL if invalid alias or algo.
void get_algo_alias(char **algo_or_alias);
#endif // ALGO_GATE_API_