aad-assignment-1/aad_coin_miner_cpu.c

211 lines
5.3 KiB
C

//
// Arquiteturas de Alto Desempenho 2025/2026
//
// DETI Coin Miner - CPU implementation
//
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <getopt.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;
}
//
// mine DETI coins using the CPU (no SIMD)
//
static void mine_coins_cpu(u64_t max_attempts, double max_time)
{
u32_t coin[14];
u32_t hash[5];
u64_t attempts = 0;
u32_t coins_found = 0;
// Initialize coin template: "DETI coin 2 " + variable content + "\n\x80"
memset(coin, 0, sizeof(coin));
// "DETI coin 2 " at the beginning
((u08_t *)coin)[0x0 ^ 3] = 'D';
((u08_t *)coin)[0x1 ^ 3] = 'E';
((u08_t *)coin)[0x2 ^ 3] = 'T';
((u08_t *)coin)[0x3 ^ 3] = 'I';
((u08_t *)coin)[0x4 ^ 3] = ' ';
((u08_t *)coin)[0x5 ^ 3] = 'c';
((u08_t *)coin)[0x6 ^ 3] = 'o';
((u08_t *)coin)[0x7 ^ 3] = 'i';
((u08_t *)coin)[0x8 ^ 3] = 'n';
((u08_t *)coin)[0x9 ^ 3] = ' ';
((u08_t *)coin)[0xa ^ 3] = '2';
((u08_t *)coin)[0xb ^ 3] = ' ';
// Newline at position 54, padding at 55
((u08_t *)coin)[0x36 ^ 3] = '\n';
((u08_t *)coin)[0x37 ^ 3] = 0x80;
// Variable part: positions 12-53 (42 bytes)
// Initialize with a pattern
for(int i = 12; i < 54; i++)
((u08_t *)coin)[i ^ 3] = 'A' + (i - 12) % 26;
printf("Mining DETI coins using CPU (no SIMD)...\n");
if(max_attempts > 0 && max_time > 0)
printf("Will stop after %llu attempts OR %.2f seconds (whichever comes first)\n",
(unsigned long long)max_attempts, max_time);
else if(max_attempts > 0)
printf("Will stop after %llu attempts\n", (unsigned long long)max_attempts);
else if(max_time > 0)
printf("Will stop after %.2f seconds\n", max_time);
else
printf("Running indefinitely until Ctrl+C...\n");
printf("Press Ctrl+C to stop\n\n");
double start_time = get_wall_time();
while(keep_running)
{
// Check stopping conditions
if(max_attempts > 0 && attempts >= max_attempts)
break;
double elapsed = get_wall_time() - start_time;
if(max_time > 0 && elapsed >= max_time)
break;
// Compute SHA1 hash
sha1(coin, hash);
attempts++;
// Check if it's a valid coin
if(is_valid_coin(hash))
{
coins_found++;
printf("COIN FOUND! (attempt %llu)\n", (unsigned long long)attempts);
save_coin(coin);
}
// Update the variable part (simple counter-based approach)
// Increment from the end to beginning
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
}
}
// Print progress every 1M attempts
if(attempts % 1000000 == 0)
{
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 any remaining coins
save_coin(NULL);
}
void print_usage(const char *prog_name)
{
printf("Usage: %s [OPTIONS]\n", prog_name);
printf("Options:\n");
printf(" -a <attempts> Maximum number of attempts\n");
printf(" -t <seconds> Maximum time in seconds\n");
printf(" -h Show this help message\n");
printf("\nExamples:\n");
printf(" %s -a 1000000 # Run for 1M attempts\n", prog_name);
printf(" %s -t 60 # Run for 60 seconds\n", prog_name);
printf(" %s -a 1000000 -t 60 # Stop at 1M attempts OR 60s (whichever first)\n", prog_name);
printf(" %s # Run indefinitely until Ctrl+C\n", prog_name);
}
int main(int argc, char *argv[])
{
u64_t max_attempts = 0;
double max_time = 0;
int opt;
// Set up signal handler for graceful shutdown
signal(SIGINT, signal_handler);
// Parse command line options
while((opt = getopt(argc, argv, "a:t:h")) != -1)
{
switch(opt)
{
case 'a':
max_attempts = strtoull(optarg, NULL, 10);
break;
case 't':
max_time = atof(optarg);
break;
case 'h':
print_usage(argv[0]);
return 0;
default:
print_usage(argv[0]);
return 1;
}
}
mine_coins_cpu(max_attempts, max_time);
return 0;
}