-
Notifications
You must be signed in to change notification settings - Fork 0
/
brower_walk.cpp
165 lines (123 loc) · 4.67 KB
/
brower_walk.cpp
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
#include <iostream>
#include <ctime>
#include <chrono>
#include <math.h>
#include <vector>
#include <cinttypes>
#ifndef _MSC_VER
#include <sys/time.h>
#endif
#include "data.h"
#include "log.h"
#include <thread>
#include <cstring>
#include "picohash.h"
#include "brower_walk_cuda.h"
#include <string>
#include <sstream>
template<typename T>
std::string to_string(T value) {
std::ostringstream os;
os << value;
return os.str();
}
static const int UINT64_BYTE_COUNT = 8;
using namespace std;
uint64_t WALK_SIZE = (1024 * 1024 * 512) / 8;
uint64_t NUM_STEPS = pow(2, 19);
long long getLongLong(unsigned char *ca, bool differentEndian);
void uint64ToByteArr(uint64_t val, char result[UINT64_BYTE_COUNT]);
uint64_t xorByteArray(const char bytes[32], int left_start, int right_start) {
char result[UINT64_BYTE_COUNT];
for (int i = 0; i < UINT64_BYTE_COUNT; i++) {
result[i] = (bytes[i + left_start] ^ bytes[i + right_start]);
}
return getLongLong(reinterpret_cast<unsigned char *>(result), true);
}
long long getLongLong(unsigned char *ca, bool differentEndian) {
long long retVal;
if (differentEndian) {
for (int i = 0; i < 4; i++) {
unsigned char _tmpCh = ca[i];
ca[i] = ca[7 - i];
ca[7 - i] = _tmpCh;
}
}
retVal = *reinterpret_cast<unsigned long long *>(ca);
return retVal;
}
#ifndef _MSC_VER
uint64_t gettime() {
struct timeval tv;
gettimeofday(&tv, NULL);
unsigned long long millisecondsSinceEpoch =
(unsigned long long) (tv.tv_sec) * 1000 +
(unsigned long long) (tv.tv_usec) / 1000;
return millisecondsSinceEpoch;
}
#endif
std::string bytesToHexStr(const unsigned char *digest, char *buf, unsigned int size) {
buf[2 * size] = 0;
for (int i = 0; i < size; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
return std::string(buf);
}
float walk_wrapper(unsigned char block_header[], size_t block_header_size) {
// CUDA/OPENCL notes: this can be done in the CPU and main memory
picohash_ctx_t block_header_context;
char header_digest[PICOHASH_SHA256_DIGEST_LENGTH];
picohash_init_sha256(&block_header_context);
picohash_update(&block_header_context, block_header, block_header_size);
picohash_final(&block_header_context, header_digest);
uint64_t s0 = xorByteArray(header_digest, 0, 16);
uint64_t s1 = xorByteArray(header_digest, 8, 24);
// CUDA/OPENCL notes: this memory should be allocated in the system RAM
auto *consumed_steps = new uint64_t[NUM_STEPS];
#ifndef _MSC_VER
uint64_t start_path_creation_time = gettime();
#endif
// CUDA/OPENCL notes: this memory should be allocated in the GPU
uint64_t * walk_path_gpu;
// CUDA/OPENCL notes: this is writing the memory in the GPU and should run as a GPU process
brower_walk_init_wrapper(WALK_SIZE, s0, s1, &walk_path_gpu);
// CUDA/OPENCL notes: this function profiling is not necessary and can be omitted
#ifndef _MSC_VER
uint64_t do_walk_start_time = gettime();
#endif
// CUDA/OPENCL notes: steps through the memory of the GPU
brower_walk_wrapper(NUM_STEPS, WALK_SIZE, walk_path_gpu, consumed_steps);
// CUDA/OPENCL notes: done with GPU processes and memory. it can be cleaned up. The rest of the function can be
// run in the CPU and main memory
char new_val_byte_array[UINT64_BYTE_COUNT];
picohash_ctx_t path_context;
picohash_init_sha256(&path_context);
for (int i=0; i < NUM_STEPS; i++) {
uint64ToByteArr(consumed_steps[i], new_val_byte_array);
picohash_update(&path_context, new_val_byte_array, UINT64_BYTE_COUNT);
}
char path_digest[PICOHASH_SHA256_DIGEST_LENGTH];
char path_digest_str[2*PICOHASH_SHA256_DIGEST_LENGTH+1];
picohash_final(&path_context, path_digest);
const string &final_hash = bytesToHexStr(reinterpret_cast<const unsigned char *>(path_digest),
path_digest_str,
PICOHASH_SHA256_DIGEST_LENGTH);
log("final hash: " + final_hash);
#ifdef _MSC_VER
return 0.0;
#else
log("path creation time: " + to_string((float) (do_walk_start_time - start_path_creation_time) / 1000));
log("walk time: " + to_string((float) (gettime() - do_walk_start_time) / 1000));
float total_time = (float) (gettime() - start_path_creation_time) / 1000;
log("total time: " + to_string(total_time) + "\n");
return total_time;
#endif
}
void uint64ToByteArr(const uint64_t val, char result[UINT64_BYTE_COUNT]) {
auto *p = (char *) &val;
for (int i = 0; i < 8; i++) {
result[i] = p[7 - i];
}
}
float mine() {
return walk_wrapper(block_header, sizeof(block_header));
}