158 lines
5.2 KiB
Plaintext
158 lines
5.2 KiB
Plaintext
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cstdint>
|
|
#include <cuda_runtime.h>
|
|
#include <curand_kernel.h>
|
|
#include <sha512.cuh>
|
|
#include <arpa/inet.h>
|
|
#include <ed25519.cuh>
|
|
#include <edsign.cuh>
|
|
__device__ __constant__ char hexDigitsConst[17] = "0123456789abcdef";
|
|
using Address = unsigned char[16];
|
|
using Key = unsigned char[32];
|
|
struct KeysBox {
|
|
Key PublicKey;
|
|
Key PrivateKey;
|
|
};
|
|
struct option {
|
|
unsigned high = 0x10;
|
|
};
|
|
__device__ static option conf;
|
|
struct ds64 {
|
|
char data[65];
|
|
};
|
|
struct ds46 {
|
|
char data[46];
|
|
};
|
|
__device__ ds64 KeyToString(const unsigned char* key) noexcept {
|
|
ds64 str;
|
|
const char* hexDigits = hexDigitsConst;
|
|
for (unsigned char i = 0; i < 32; i++) {
|
|
str.data[2 * i] = hexDigits[key[i] >> 4];
|
|
str.data[2 * i + 1] = hexDigits[key[i] & 0x0F];
|
|
}
|
|
str.data[64] = '\0';
|
|
return str;
|
|
}
|
|
__device__ ds46 getAddress(const unsigned char rawAddr[16]) noexcept {
|
|
ds46 addrStr;
|
|
#ifdef __CUDA_ARCH__
|
|
const char* hexDigits = hexDigitsConst;
|
|
#else
|
|
const char* hexDigits = "0123456789abcdef";
|
|
#endif
|
|
int pos = 0;
|
|
for (int group = 0; group < 8; group++) {
|
|
int idx = group * 2;
|
|
addrStr.data[pos++] = hexDigits[rawAddr[idx] >> 4];
|
|
addrStr.data[pos++] = hexDigits[rawAddr[idx] & 0x0F];
|
|
addrStr.data[pos++] = hexDigits[rawAddr[idx + 1] >> 4];
|
|
addrStr.data[pos++] = hexDigits[rawAddr[idx + 1] & 0x0F];
|
|
if (group < 7) {
|
|
addrStr.data[pos++] = ':';
|
|
}
|
|
}
|
|
addrStr.data[pos] = '\0';
|
|
return addrStr;
|
|
}
|
|
__device__ void getRawAddress(int lErase, Key& InvertedPublicKey, Address& rawAddr) noexcept {
|
|
lErase++;
|
|
const int bitsToShift = lErase % 8;
|
|
const int start = lErase / 8;
|
|
if (bitsToShift != 0) {
|
|
for (int i = start; i < start + 15; i++) {
|
|
InvertedPublicKey[i] = static_cast<unsigned char>((InvertedPublicKey[i] << bitsToShift) | (InvertedPublicKey[i + 1] >> (8 - bitsToShift)));
|
|
}
|
|
}
|
|
rawAddr[0] = 0x02;
|
|
rawAddr[1] = static_cast<unsigned char>(lErase - 1);
|
|
memcpy(&rawAddr[2], &InvertedPublicKey[start], 14);
|
|
}
|
|
__device__ unsigned long long xorshift128plus(unsigned long long* state) {
|
|
unsigned long long x = state[0];
|
|
const unsigned long long y = state[1];
|
|
state[0] = y;
|
|
x ^= x << 23;
|
|
x ^= x >> 17;
|
|
x ^= y ^ (y >> 26);
|
|
state[1] = x;
|
|
return x + y;
|
|
}
|
|
__device__ unsigned char zeroCounter(unsigned int x) {
|
|
if (x == 0)
|
|
return 32;
|
|
#ifdef __CUDA_ARCH__
|
|
return static_cast<unsigned char>(__clz(x));
|
|
#else
|
|
return static_cast<unsigned char>(__builtin_clz(x));
|
|
#endif
|
|
}
|
|
__device__ unsigned char getZeros(const unsigned char* v) {
|
|
unsigned char leadZeros = 0;
|
|
for (int i = 0; i < 32; i += 4) {
|
|
unsigned word = (static_cast<unsigned>(v[i]) << 24) | (static_cast<unsigned>(v[i + 1]) << 16) | (static_cast<unsigned>(v[i + 2]) << 8) | (static_cast<unsigned>(v[i + 3]));
|
|
if (word == 0)
|
|
leadZeros += 32;
|
|
else {
|
|
leadZeros += zeroCounter(word);
|
|
break;
|
|
}
|
|
}
|
|
return leadZeros;
|
|
}
|
|
__global__ void initRandStates(curandState* randStates) {
|
|
int id = blockIdx.x * blockDim.x + threadIdx.x;
|
|
curand_init((unsigned long long)clock64() + id, id, 0, &randStates[id]);
|
|
}
|
|
__device__ void generateRandomBytes(unsigned char* buf, unsigned long size, curandState* state) {
|
|
for (unsigned long i = 0; i < size; i++) {
|
|
buf[i] = curand(state) & 0xFF;
|
|
}
|
|
}
|
|
__device__ void invertKey(const unsigned char* key, unsigned char* inverted) {
|
|
for (int i = 0; i < 32; i++)
|
|
inverted[i] = key[i] ^ 0xFF;
|
|
}
|
|
__device__ void compact_wipe(void* data, unsigned long length) {
|
|
volatile unsigned char* p = (volatile unsigned char*)data;
|
|
while (length--) {
|
|
*p++ = 0;
|
|
}
|
|
}
|
|
__device__ void ed25519_keygen(unsigned char private_key[64], unsigned char public_key[32], unsigned char random_seed[32]) {
|
|
edsign_sec_to_pub(public_key, random_seed);
|
|
memcpy(private_key, random_seed, 32);
|
|
memcpy(private_key + 32, public_key, 32);
|
|
compact_wipe(random_seed, 32);
|
|
}
|
|
__global__ __launch_bounds__(256) void minerKernel(curandState* randStates) {
|
|
int thid = blockIdx.x * blockDim.x + threadIdx.x;
|
|
curandState localState = randStates[thid];
|
|
Key seed;
|
|
generateRandomBytes(seed, sizeof(seed), &localState);
|
|
while (true) {
|
|
generateRandomBytes(seed, sizeof(seed), &localState);
|
|
KeysBox keys;
|
|
ed25519_keygen(keys.PrivateKey, keys.PublicKey, seed);
|
|
if (unsigned zeros = getZeros(keys.PublicKey); zeros > atomicMax(&conf.high, (unsigned)zeros)) {
|
|
Key inv;
|
|
Address raw;
|
|
invertKey(keys.PublicKey, inv);
|
|
getRawAddress(zeros, inv, raw);
|
|
printf("\nIPv6:\t%s\nPK:\t%s\nSK:\t%s\n", getAddress(raw).data, KeyToString(keys.PublicKey).data, KeyToString(keys.PrivateKey).data);
|
|
}
|
|
__syncthreads();
|
|
}
|
|
//randStates[thid] = localState;
|
|
}
|
|
int main() {
|
|
curandState* d_randStates;
|
|
cudaMalloc(&d_randStates, 1024 * sizeof(curandState));
|
|
initRandStates << <4, 256 >> > (d_randStates);
|
|
cudaDeviceSynchronize();
|
|
minerKernel << <4, 256 >> > (d_randStates);
|
|
cudaDeviceSynchronize();
|
|
cudaFree(d_randStates);
|
|
return 0;
|
|
} |