427 lines
12 KiB
C
427 lines
12 KiB
C
//
|
|
// Arquiteturas de Alto Desempenho 2025/2026
|
|
//
|
|
// DETI Coin Miner - SIMD implementation (AVX/AVX2/AVX512F)
|
|
//
|
|
|
|
#include <time.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include "aad_data_types.h"
|
|
#include "aad_utilities.h"
|
|
#include "aad_sha1_cpu.h"
|
|
#include "aad_vault.h"
|
|
|
|
static volatile int keep_running = 1;
|
|
|
|
void signal_handler(int signum)
|
|
{
|
|
(void)signum;
|
|
keep_running = 0;
|
|
}
|
|
|
|
//
|
|
// check if a hash starts with aad20250
|
|
//
|
|
static int is_valid_coin(u32_t *hash)
|
|
{
|
|
return hash[0] == 0xAAD20250u;
|
|
}
|
|
|
|
// Get current wall time in seconds
|
|
static double get_wall_time(void)
|
|
{
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return (double)ts.tv_sec + (double)ts.tv_nsec * 1.0e-9;
|
|
}
|
|
|
|
//
|
|
// increment coin variable part using the same logic as CPU miner
|
|
// returns 0 if overflow (all positions wrapped around), 1 otherwise
|
|
//
|
|
static int increment_coin(u32_t coin[14])
|
|
{
|
|
// Increment the variable part using byte-by-byte logic with carry
|
|
// Increment from the end to beginning (positions 53 down to 12)
|
|
int pos = 53;
|
|
while(pos >= 12)
|
|
{
|
|
u08_t *byte = &((u08_t *)coin)[pos ^ 3];
|
|
if(*byte == '\n' || *byte == 0x80)
|
|
*byte = 32; // Start from space
|
|
|
|
(*byte)++;
|
|
|
|
// Skip newline character
|
|
if(*byte == '\n')
|
|
(*byte)++;
|
|
|
|
// Wrap around at 127 (printable ASCII limit)
|
|
if(*byte >= 127)
|
|
{
|
|
*byte = 32; // Reset to space
|
|
pos--; // Carry to next position
|
|
}
|
|
else
|
|
{
|
|
break; // No carry needed
|
|
}
|
|
}
|
|
|
|
// Return 0 if we carried all the way through (overflow), 1 otherwise
|
|
return (pos >= 12);
|
|
}
|
|
|
|
//
|
|
// prepare interleaved data for SIMD processing
|
|
//
|
|
static void prepare_coins(u32_t base_coin[14], u32_t *interleaved_data, int simd_width)
|
|
{
|
|
for(int lane = 0; lane < simd_width; lane++)
|
|
{
|
|
u32_t coin[14];
|
|
memcpy(coin, base_coin, sizeof(coin));
|
|
|
|
// Interleave the data
|
|
for(int idx = 0; idx < 14; idx++)
|
|
{
|
|
interleaved_data[idx * simd_width + lane] = coin[idx];
|
|
}
|
|
|
|
// Increment the base coin for the next lane
|
|
increment_coin(base_coin);
|
|
}
|
|
}
|
|
|
|
//
|
|
// extract individual hashes from interleaved hash data
|
|
//
|
|
static void extract_hashes(u32_t *interleaved_hash, u32_t hashes[][5], int simd_width)
|
|
{
|
|
for(int lane = 0; lane < simd_width; lane++)
|
|
{
|
|
for(int idx = 0; idx < 5; idx++)
|
|
{
|
|
hashes[lane][idx] = interleaved_hash[idx * simd_width + lane];
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// extract individual coins from interleaved data
|
|
//
|
|
static void extract_coins(u32_t *interleaved_data, u32_t coins[][14], int simd_width)
|
|
{
|
|
for(int lane = 0; lane < simd_width; lane++)
|
|
{
|
|
for(int idx = 0; idx < 14; idx++)
|
|
{
|
|
coins[lane][idx] = interleaved_data[idx * simd_width + lane];
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(__AVX__)
|
|
//
|
|
// mine DETI coins using AVX (4-way SIMD)
|
|
//
|
|
__attribute__((unused))
|
|
static void mine_coins_avx(u64_t max_attempts)
|
|
{
|
|
const int SIMD_WIDTH = 4;
|
|
u32_t base_coin[14];
|
|
u32_t interleaved_data[14 * SIMD_WIDTH] __attribute__((aligned(16)));
|
|
u32_t interleaved_hash[5 * SIMD_WIDTH] __attribute__((aligned(16)));
|
|
u64_t attempts = 0;
|
|
u32_t coins_found = 0;
|
|
|
|
// Initialize base coin template
|
|
memset(base_coin, 0, sizeof(base_coin));
|
|
((u08_t *)base_coin)[0x0 ^ 3] = 'D';
|
|
((u08_t *)base_coin)[0x1 ^ 3] = 'E';
|
|
((u08_t *)base_coin)[0x2 ^ 3] = 'T';
|
|
((u08_t *)base_coin)[0x3 ^ 3] = 'I';
|
|
((u08_t *)base_coin)[0x4 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x5 ^ 3] = 'c';
|
|
((u08_t *)base_coin)[0x6 ^ 3] = 'o';
|
|
((u08_t *)base_coin)[0x7 ^ 3] = 'i';
|
|
((u08_t *)base_coin)[0x8 ^ 3] = 'n';
|
|
((u08_t *)base_coin)[0x9 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0xa ^ 3] = '2';
|
|
((u08_t *)base_coin)[0xb ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x36 ^ 3] = '\n';
|
|
((u08_t *)base_coin)[0x37 ^ 3] = 0x80;
|
|
|
|
// Initialize variable part with A-Z cycling pattern (same as CPU miner)
|
|
for(int i = 12; i < 54; i++)
|
|
((u08_t *)base_coin)[i ^ 3] = 'A' + (i - 12) % 26;
|
|
|
|
printf("Mining DETI coins using AVX (4-way SIMD)...\n");
|
|
printf("Press Ctrl+C to stop\n\n");
|
|
|
|
double start_time = get_wall_time();
|
|
|
|
while(keep_running && (max_attempts == 0 || attempts < max_attempts))
|
|
{
|
|
// Prepare coins for this batch
|
|
prepare_coins(base_coin, interleaved_data, SIMD_WIDTH);
|
|
|
|
// Compute SHA1 hashes
|
|
sha1_avx((v4si *)interleaved_data, (v4si *)interleaved_hash);
|
|
attempts += SIMD_WIDTH;
|
|
|
|
// Check each lane for valid coins
|
|
u32_t hashes[SIMD_WIDTH][5];
|
|
extract_hashes(interleaved_hash, hashes, SIMD_WIDTH);
|
|
|
|
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
|
{
|
|
if(is_valid_coin(hashes[lane]))
|
|
{
|
|
coins_found++;
|
|
u32_t coins[SIMD_WIDTH][14];
|
|
extract_coins(interleaved_data, coins, SIMD_WIDTH);
|
|
printf("COIN FOUND! (attempt %llu, lane %d)\n",
|
|
(unsigned long long)(attempts - SIMD_WIDTH + lane), lane);
|
|
save_coin(coins[lane]);
|
|
}
|
|
}
|
|
|
|
// Print progress every 1M attempts
|
|
if(attempts % 1000000 < SIMD_WIDTH)
|
|
{
|
|
double elapsed = get_wall_time() - start_time;
|
|
double rate = attempts / elapsed;
|
|
printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n",
|
|
(unsigned long long)attempts, rate / 1e6, coins_found, elapsed);
|
|
}
|
|
}
|
|
|
|
double total_time = get_wall_time() - start_time;
|
|
|
|
printf("\n=== Mining Statistics ===\n");
|
|
printf("Total attempts: %llu\n", (unsigned long long)attempts);
|
|
printf("Total time: %.2f seconds\n", total_time);
|
|
printf("Average rate: %.2f attempts/second\n", attempts / total_time);
|
|
printf("Coins found: %u\n", coins_found);
|
|
|
|
save_coin(NULL);
|
|
}
|
|
#endif
|
|
|
|
#if defined(__AVX2__)
|
|
//
|
|
// mine DETI coins using AVX2 (8-way SIMD)
|
|
//
|
|
__attribute__((unused))
|
|
static void mine_coins_avx2(u64_t max_attempts)
|
|
{
|
|
const int SIMD_WIDTH = 8;
|
|
u32_t base_coin[14];
|
|
u32_t interleaved_data[14 * SIMD_WIDTH] __attribute__((aligned(32)));
|
|
u32_t interleaved_hash[5 * SIMD_WIDTH] __attribute__((aligned(32)));
|
|
u64_t attempts = 0;
|
|
u32_t coins_found = 0;
|
|
|
|
// Initialize base coin template
|
|
memset(base_coin, 0, sizeof(base_coin));
|
|
((u08_t *)base_coin)[0x0 ^ 3] = 'D';
|
|
((u08_t *)base_coin)[0x1 ^ 3] = 'E';
|
|
((u08_t *)base_coin)[0x2 ^ 3] = 'T';
|
|
((u08_t *)base_coin)[0x3 ^ 3] = 'I';
|
|
((u08_t *)base_coin)[0x4 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x5 ^ 3] = 'c';
|
|
((u08_t *)base_coin)[0x6 ^ 3] = 'o';
|
|
((u08_t *)base_coin)[0x7 ^ 3] = 'i';
|
|
((u08_t *)base_coin)[0x8 ^ 3] = 'n';
|
|
((u08_t *)base_coin)[0x9 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0xa ^ 3] = '2';
|
|
((u08_t *)base_coin)[0xb ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x36 ^ 3] = '\n';
|
|
((u08_t *)base_coin)[0x37 ^ 3] = 0x80;
|
|
|
|
// Initialize variable part with A-Z cycling pattern (same as CPU miner)
|
|
for(int i = 12; i < 54; i++)
|
|
((u08_t *)base_coin)[i ^ 3] = 'A' + (i - 12) % 26;
|
|
|
|
printf("Mining DETI coins using AVX2 (8-way SIMD)...\n");
|
|
printf("Press Ctrl+C to stop\n\n");
|
|
|
|
double start_time = get_wall_time();
|
|
|
|
while(keep_running && (max_attempts == 0 || attempts < max_attempts))
|
|
{
|
|
prepare_coins(base_coin, interleaved_data, SIMD_WIDTH);
|
|
sha1_avx2((v8si *)interleaved_data, (v8si *)interleaved_hash);
|
|
attempts += SIMD_WIDTH;
|
|
|
|
u32_t hashes[SIMD_WIDTH][5];
|
|
extract_hashes(interleaved_hash, hashes, SIMD_WIDTH);
|
|
|
|
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
|
{
|
|
if(is_valid_coin(hashes[lane]))
|
|
{
|
|
coins_found++;
|
|
u32_t coins[SIMD_WIDTH][14];
|
|
extract_coins(interleaved_data, coins, SIMD_WIDTH);
|
|
printf("COIN FOUND! (attempt %llu, lane %d)\n",
|
|
(unsigned long long)(attempts - SIMD_WIDTH + lane), lane);
|
|
save_coin(coins[lane]);
|
|
}
|
|
}
|
|
|
|
if(attempts % 1000000 < SIMD_WIDTH)
|
|
{
|
|
double elapsed = get_wall_time() - start_time;
|
|
double rate = attempts / elapsed;
|
|
printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n",
|
|
(unsigned long long)attempts, rate / 1e6, coins_found, elapsed);
|
|
}
|
|
}
|
|
|
|
double total_time = get_wall_time() - start_time;
|
|
|
|
printf("\n=== Mining Statistics ===\n");
|
|
printf("Total attempts: %llu\n", (unsigned long long)attempts);
|
|
printf("Total time: %.2f seconds\n", total_time);
|
|
printf("Average rate: %.2f attempts/second\n", attempts / total_time);
|
|
printf("Coins found: %u\n", coins_found);
|
|
|
|
save_coin(NULL);
|
|
}
|
|
#endif
|
|
|
|
#if defined(__AVX2__)
|
|
#include <omp.h>
|
|
//
|
|
// mine DETI coins using AVX2 (8-way SIMD) + OpenMP
|
|
//
|
|
__attribute__((unused))
|
|
static void mine_coins_avx2_omp(u64_t max_attempts)
|
|
{
|
|
const int SIMD_WIDTH = 8;
|
|
int num_threads = omp_get_max_threads();
|
|
u64_t attempts = 0;
|
|
u32_t coins_found = 0;
|
|
|
|
printf("Mining DETI coins using AVX2 (8-way SIMD) + OpenMP (%d threads)...\n", num_threads);
|
|
printf("Press Ctrl+C to stop\n\n");
|
|
|
|
double start_time = get_wall_time();
|
|
|
|
#pragma omp parallel
|
|
{
|
|
u32_t base_coin[14];
|
|
u32_t interleaved_data[14 * SIMD_WIDTH] __attribute__((aligned(32)));
|
|
u32_t interleaved_hash[5 * SIMD_WIDTH] __attribute__((aligned(32)));
|
|
u64_t thread_attempts = 0;
|
|
|
|
// Initialize base coin template (unique per thread)
|
|
memset(base_coin, 0, sizeof(base_coin));
|
|
((u08_t *)base_coin)[0x0 ^ 3] = 'D';
|
|
((u08_t *)base_coin)[0x1 ^ 3] = 'E';
|
|
((u08_t *)base_coin)[0x2 ^ 3] = 'T';
|
|
((u08_t *)base_coin)[0x3 ^ 3] = 'I';
|
|
((u08_t *)base_coin)[0x4 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x5 ^ 3] = 'c';
|
|
((u08_t *)base_coin)[0x6 ^ 3] = 'o';
|
|
((u08_t *)base_coin)[0x7 ^ 3] = 'i';
|
|
((u08_t *)base_coin)[0x8 ^ 3] = 'n';
|
|
((u08_t *)base_coin)[0x9 ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0xa ^ 3] = '2';
|
|
((u08_t *)base_coin)[0xb ^ 3] = ' ';
|
|
((u08_t *)base_coin)[0x36 ^ 3] = '\n';
|
|
((u08_t *)base_coin)[0x37 ^ 3] = 0x80;
|
|
|
|
// Initialize variable part with A-Z cycling pattern (offset per thread)
|
|
int thread_id = omp_get_thread_num();
|
|
for(int i = 12; i < 54; i++)
|
|
((u08_t *)base_coin)[i ^ 3] = 'A' + ((i - 12 + thread_id * SIMD_WIDTH) % 26);
|
|
|
|
while(keep_running && (max_attempts == 0 || (attempts + thread_attempts) < max_attempts))
|
|
{
|
|
prepare_coins(base_coin, interleaved_data, SIMD_WIDTH);
|
|
sha1_avx2((v8si *)interleaved_data, (v8si *)interleaved_hash);
|
|
thread_attempts += SIMD_WIDTH;
|
|
|
|
u32_t hashes[SIMD_WIDTH][5];
|
|
extract_hashes(interleaved_hash, hashes, SIMD_WIDTH);
|
|
|
|
for(int lane = 0; lane < SIMD_WIDTH; lane++)
|
|
{
|
|
if(is_valid_coin(hashes[lane]))
|
|
{
|
|
#pragma omp critical
|
|
{
|
|
coins_found++;
|
|
u32_t coins[SIMD_WIDTH][14];
|
|
extract_coins(interleaved_data, coins, SIMD_WIDTH);
|
|
printf("COIN FOUND! (attempt %llu, thread %d, lane %d)\n",
|
|
(unsigned long long)(attempts + thread_attempts - SIMD_WIDTH + lane),
|
|
thread_id, lane);
|
|
save_coin(coins[lane]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print progress every 1M attempts (per thread)
|
|
if(thread_attempts % 1000000 < SIMD_WIDTH)
|
|
{
|
|
#pragma omp critical
|
|
{
|
|
double elapsed = get_wall_time() - start_time;
|
|
double rate = (attempts + thread_attempts) / elapsed;
|
|
printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u, Elapsed: %.2fs\n",
|
|
(unsigned long long)(attempts + thread_attempts), rate / 1e6, coins_found, elapsed);
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma omp atomic
|
|
attempts += thread_attempts;
|
|
}
|
|
|
|
double total_time = get_wall_time() - start_time;
|
|
|
|
printf("\n=== Mining Statistics ===\n");
|
|
printf("Total attempts: %llu\n", (unsigned long long)attempts);
|
|
printf("Total time: %.2f seconds\n", total_time);
|
|
printf("Average rate: %.2f attempts/second\n", attempts / total_time);
|
|
printf("Coins found: %u\n", coins_found);
|
|
|
|
save_coin(NULL);
|
|
}
|
|
#endif
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
u64_t max_attempts = 0;
|
|
|
|
signal(SIGINT, signal_handler);
|
|
|
|
if(argc > 1)
|
|
max_attempts = strtoull(argv[1], NULL, 10);
|
|
|
|
#if defined(__AVX2__)
|
|
if(argc > 2 && strcmp(argv[2], "omp") == 0) {
|
|
printf("Using AVX2 + OpenMP implementation\n");
|
|
mine_coins_avx2_omp(max_attempts);
|
|
} else {
|
|
printf("Using AVX2 implementation\n");
|
|
mine_coins_avx2(max_attempts);
|
|
}
|
|
#elif defined(__AVX__)
|
|
printf("Using AVX implementation\n");
|
|
mine_coins_avx(max_attempts);
|
|
#else
|
|
printf("Error: No SIMD instruction set available. Compile with -mavx or -mavx2\n");
|
|
return 1;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|