// // Arquiteturas de Alto Desempenho 2025/2026 // // DETI Coin Miner - WebAssembly implementation with SIMD support // #include #include #include #include #include "aad_data_types.h" #ifdef __EMSCRIPTEN__ #include #include "aad_sha1_wasm.h" #else #include "aad_sha1_cpu.h" #include "aad_utilities.h" #include "aad_vault.h" #endif // WASM SIMD support #if defined(__wasm_simd128__) #include #endif // Global mining state static volatile int keep_running = 1; static volatile int use_simd = 0; static u64_t total_attempts = 0; static u32_t coins_found = 0; static double mining_start_time = 0; static double pause_time_offset = 0; static double last_pause_time = 0; static u32_t found_coins[1024][14]; static u32_t found_coins_count = 0; // // Check if a hash starts with aad20250 // static int is_valid_coin(u32_t *hash) { return hash[0] == 0xAAD20250u; } // // Increment coin variable part (positions 12-53) // static int increment_coin(u32_t coin[14]) { int pos = 53; while(pos >= 12) { u08_t *byte = &((u08_t *)coin)[pos ^ 3]; if(*byte == '\n' || *byte == 0x80) *byte = 32; (*byte)++; if(*byte == '\n') (*byte)++; if(*byte >= 127) { *byte = 32; pos--; } else { break; } } return (pos >= 12); } // // Get current time in seconds // static double get_time() { #ifdef __EMSCRIPTEN__ return emscripten_get_now() / 1000.0; #else struct timespec ts; clock_gettime(CLOCK_MONOTONIC_RAW, &ts); return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9; #endif } #if defined(__wasm_simd128__) // // Helper macro for Left Rotate (ROTL) using SIMD shifts // CORRECTION: Used wasm_u32x4_shr instead of incorrect wasm_i32x4_shr_u // #define SIMD_ROTL(x, n) wasm_v128_or(wasm_i32x4_shl(x, n), wasm_u32x4_shr(x, 32 - n)) // // SIMD implementation for WebAssembly (4-way parallel) // static void prepare_coins_simd(u32_t base_coin[14], u32_t *interleaved_data) { const int SIMD_WIDTH = 4; for(int lane = 0; lane < SIMD_WIDTH; lane++) { u32_t coin[14]; memcpy(coin, base_coin, sizeof(coin)); for(int idx = 0; idx < 14; idx++) { interleaved_data[idx * SIMD_WIDTH + lane] = coin[idx]; } increment_coin(base_coin); } } static void extract_hashes_simd(u32_t *interleaved_hash, u32_t hashes[][5]) { const int SIMD_WIDTH = 4; for(int lane = 0; lane < SIMD_WIDTH; lane++) { for(int idx = 0; idx < 5; idx++) { hashes[lane][idx] = interleaved_hash[idx * SIMD_WIDTH + lane]; } } } static void extract_coins_simd(u32_t *interleaved_data, u32_t coins[][14]) { const int SIMD_WIDTH = 4; for(int lane = 0; lane < SIMD_WIDTH; lane++) { for(int idx = 0; idx < 14; idx++) { coins[lane][idx] = interleaved_data[idx * SIMD_WIDTH + lane]; } } } static void sha1_wasm_simd(u32_t *interleaved_data, u32_t *interleaved_hash) { const int SIMD_WIDTH = 4; // SHA1 State vectors v128_t a, b, c, d, e; v128_t w[80]; // Message schedule // Initial SHA1 constants a = wasm_i32x4_splat(0x67452301u); b = wasm_i32x4_splat(0xEFCDAB89u); c = wasm_i32x4_splat(0x98BADCFEu); d = wasm_i32x4_splat(0x10325476u); e = wasm_i32x4_splat(0xC3D2E1F0u); // 1. Prepare Message Schedule (Interleaved loads) // Load first 14 words for(int i = 0; i < 14; i++) { w[i] = wasm_v128_load(&interleaved_data[i * SIMD_WIDTH]); } // Standard padding (assumed handled by caller/init) w[14] = wasm_i32x4_splat(0); w[15] = wasm_i32x4_splat(440); // Length in bits (55 bytes * 8) // Expand message schedule from 16 to 80 for (int i = 16; i < 80; i++) { v128_t temp = wasm_v128_xor(w[i-3], w[i-8]); temp = wasm_v128_xor(temp, w[i-14]); temp = wasm_v128_xor(temp, w[i-16]); w[i] = SIMD_ROTL(temp, 1); } // 2. Main Loop (80 rounds) for (int i = 0; i < 80; i++) { v128_t f, k; if (i < 20) { // F1: (b & c) | (~b & d) f = wasm_v128_or(wasm_v128_and(b, c), wasm_v128_and(wasm_v128_not(b), d)); k = wasm_i32x4_splat(0x5A827999u); } else if (i < 40) { // F2: b ^ c ^ d f = wasm_v128_xor(wasm_v128_xor(b, c), d); k = wasm_i32x4_splat(0x6ED9EBA1u); } else if (i < 60) { // F3: (b & c) | (b & d) | (c & d) f = wasm_v128_or(wasm_v128_or(wasm_v128_and(b, c), wasm_v128_and(b, d)), wasm_v128_and(c, d)); k = wasm_i32x4_splat(0x8F1BBCDCu); } else { // F4: b ^ c ^ d f = wasm_v128_xor(wasm_v128_xor(b, c), d); k = wasm_i32x4_splat(0xCA62C1D6u); } // temp = ROTL(a, 5) + f + e + k + w[i] v128_t temp = wasm_i32x4_add(SIMD_ROTL(a, 5), f); temp = wasm_i32x4_add(temp, e); temp = wasm_i32x4_add(temp, k); temp = wasm_i32x4_add(temp, w[i]); e = d; d = c; c = SIMD_ROTL(b, 30); b = a; a = temp; } // 3. Add to initial state and store v128_t h0 = wasm_i32x4_add(a, wasm_i32x4_splat(0x67452301u)); v128_t h1 = wasm_i32x4_add(b, wasm_i32x4_splat(0xEFCDAB89u)); v128_t h2 = wasm_i32x4_add(c, wasm_i32x4_splat(0x98BADCFEu)); v128_t h3 = wasm_i32x4_add(d, wasm_i32x4_splat(0x10325476u)); v128_t h4 = wasm_i32x4_add(e, wasm_i32x4_splat(0xC3D2E1F0u)); // Store results back to interleaved_hash wasm_v128_store(&interleaved_hash[0 * SIMD_WIDTH], h0); wasm_v128_store(&interleaved_hash[1 * SIMD_WIDTH], h1); wasm_v128_store(&interleaved_hash[2 * SIMD_WIDTH], h2); wasm_v128_store(&interleaved_hash[3 * SIMD_WIDTH], h3); wasm_v128_store(&interleaved_hash[4 * SIMD_WIDTH], h4); } static int mine_coins_wasm_simd_internal(u32_t iterations_per_call, u32_t coin[14]) { const int SIMD_WIDTH = 4; u32_t interleaved_data[14 * SIMD_WIDTH] __attribute__((aligned(16))); u32_t interleaved_hash[5 * SIMD_WIDTH] __attribute__((aligned(16))); u32_t batches = (iterations_per_call + SIMD_WIDTH - 1) / SIMD_WIDTH; for(u32_t batch = 0; batch < batches && keep_running; batch++) { prepare_coins_simd(coin, interleaved_data); // This now uses the REAL vectorized implementation sha1_wasm_simd(interleaved_data, interleaved_hash); total_attempts += SIMD_WIDTH; u32_t hashes[SIMD_WIDTH][5]; extract_hashes_simd(interleaved_hash, hashes); for(int lane = 0; lane < SIMD_WIDTH; lane++) { if(is_valid_coin(hashes[lane])) { if(found_coins_count < 1024) { u32_t coins[SIMD_WIDTH][14]; extract_coins_simd(interleaved_data, coins); memcpy(found_coins[found_coins_count], coins[lane], sizeof(coins[lane])); found_coins_count++; } coins_found++; #ifndef __EMSCRIPTEN__ printf("COIN FOUND! (attempt %llu, lane %d)\n", (unsigned long long)(total_attempts - SIMD_WIDTH + lane), lane); #endif } } } return keep_running; } #endif // // Main mining iteration (called from JavaScript) // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif int mine_coins_wasm(u32_t iterations_per_call) { static u32_t coin[14]; static int initialized = 0; static int last_logged_mode = -1; // Track last reported mode u32_t hash[5]; // Initialize coin template on first call if(!initialized) { memset(coin, 0, sizeof(coin)); ((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] = ' '; ((u08_t *)coin)[0x36 ^ 3] = '\n'; ((u08_t *)coin)[0x37 ^ 3] = 0x80; for(int i = 12; i < 54; i++) ((u08_t *)coin)[i ^ 3] = 'A' + (i - 12) % 26; mining_start_time = get_time(); initialized = 1; } if(!keep_running) return 0; #if defined(__wasm_simd128__) if(use_simd) { if (last_logged_mode != 1) { printf("C: Running in SIMD Mode (Vectorized)\n"); last_logged_mode = 1; } return mine_coins_wasm_simd_internal(iterations_per_call, coin); } #endif if (last_logged_mode != 0) { printf("C: Running in Scalar Mode\n"); last_logged_mode = 0; } // Scalar implementation for(u32_t i = 0; i < iterations_per_call && keep_running; i++) { sha1(coin, hash); total_attempts++; if(is_valid_coin(hash)) { if(found_coins_count < 1024) { memcpy(found_coins[found_coins_count], coin, sizeof(coin)); found_coins_count++; } coins_found++; #ifndef __EMSCRIPTEN__ printf("COIN FOUND! (attempt %llu)\n", (unsigned long long)total_attempts); save_coin(coin); #endif } increment_coin(coin); } return keep_running; } // // Get mining statistics // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void get_statistics(u64_t *attempts, u32_t *coins, double *hash_rate, double *elapsed_time) { *attempts = total_attempts; *coins = coins_found; double current_time = get_time(); double actual_elapsed; if(!keep_running && last_pause_time > 0) { actual_elapsed = last_pause_time - mining_start_time - pause_time_offset; } else { actual_elapsed = current_time - mining_start_time - pause_time_offset; } *elapsed_time = actual_elapsed; *hash_rate = (actual_elapsed > 0) ? (total_attempts / actual_elapsed) : 0; } // // Enable/disable SIMD // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void set_simd_enabled(int enabled) { use_simd = enabled; printf("C: SIMD mode set to: %d\n", use_simd); } // // Check if SIMD is available // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif int is_simd_available() { #if defined(__wasm_simd128__) return 1; #else return 0; #endif } // // Get current SIMD state // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif int is_simd_enabled() { return use_simd; } // // Stop mining // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void stop_mining() { if(keep_running) { keep_running = 0; last_pause_time = get_time(); } } // // Resume mining // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void resume_mining() { if(!keep_running && last_pause_time > 0) { double pause_duration = get_time() - last_pause_time; pause_time_offset += pause_duration; keep_running = 1; last_pause_time = 0; } } // // Get found coin data // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif u32_t* get_found_coin(u32_t index) { if(index < found_coins_count) return found_coins[index]; return NULL; } // // Get number of found coins // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif u32_t get_found_coins_count() { return found_coins_count; } // // Reset mining state // #ifdef __EMSCRIPTEN__ EMSCRIPTEN_KEEPALIVE #endif void reset_mining() { keep_running = 1; total_attempts = 0; coins_found = 0; found_coins_count = 0; pause_time_offset = 0; last_pause_time = 0; mining_start_time = get_time(); } // // Main function (for standalone compilation/testing) // #ifndef __EMSCRIPTEN__ int main(int argc, char *argv[]) { u64_t max_attempts = 0; if(argc > 1) max_attempts = strtoull(argv[1], NULL, 10); printf("Mining DETI coins using WebAssembly implementation (standalone mode)...\n"); #if defined(__wasm_simd128__) printf("SIMD support: available\n"); use_simd = 1; #else printf("SIMD support: not available\n"); #endif printf("Press Ctrl+C to stop\n\n"); time_measurement(); time_measurement(); double start_time = wall_time_delta(); double last_report = start_time; while(keep_running && (max_attempts == 0 || total_attempts < max_attempts)) { mine_coins_wasm(100000); time_measurement(); double current_time = wall_time_delta() - start_time; if(current_time - last_report >= 1.0) { u64_t attempts; u32_t coins; double hash_rate, elapsed; get_statistics(&attempts, &coins, &hash_rate, &elapsed); printf("Attempts: %llu, Rate: %.2f MH/s, Coins: %u\n", (unsigned long long)attempts, hash_rate / 1e6, coins); last_report = current_time; } } time_measurement(); double total_time = wall_time_delta() - start_time; printf("\n=== Mining Statistics ===\n"); printf("Total attempts: %llu\n", (unsigned long long)total_attempts); printf("Total time: %.2f seconds\n", total_time); printf("Average rate: %.2f attempts/second\n", total_attempts / total_time); printf("Coins found: %u\n", coins_found); save_coin(NULL); return 0; } #endif