Better usability in browser
Signed-off-by: Tiago Garcia <tiago.rgarcia@ua.pt>
This commit is contained in:
parent
fa06494b59
commit
a906816cd4
|
|
@ -24,6 +24,8 @@ static volatile int keep_running = 1;
|
||||||
static u64_t total_attempts = 0;
|
static u64_t total_attempts = 0;
|
||||||
static u32_t coins_found = 0;
|
static u32_t coins_found = 0;
|
||||||
static double mining_start_time = 0;
|
static double mining_start_time = 0;
|
||||||
|
static double pause_time_offset = 0; // Track paused time
|
||||||
|
static double last_pause_time = 0; // When mining was paused
|
||||||
static u32_t found_coins[1024][14]; // Store up to 1024 found coins
|
static u32_t found_coins[1024][14]; // Store up to 1024 found coins
|
||||||
static u32_t found_coins_count = 0;
|
static u32_t found_coins_count = 0;
|
||||||
|
|
||||||
|
|
@ -158,8 +160,20 @@ void get_statistics(u64_t *attempts, u32_t *coins, double *hash_rate, double *el
|
||||||
{
|
{
|
||||||
*attempts = total_attempts;
|
*attempts = total_attempts;
|
||||||
*coins = coins_found;
|
*coins = coins_found;
|
||||||
*elapsed_time = get_time() - mining_start_time;
|
|
||||||
*hash_rate = (*elapsed_time > 0) ? (total_attempts / *elapsed_time) : 0;
|
double current_time = get_time();
|
||||||
|
double actual_elapsed;
|
||||||
|
|
||||||
|
if(!keep_running && last_pause_time > 0) {
|
||||||
|
// If paused, use the paused time
|
||||||
|
actual_elapsed = last_pause_time - mining_start_time - pause_time_offset;
|
||||||
|
} else {
|
||||||
|
// If running, calculate normally
|
||||||
|
actual_elapsed = current_time - mining_start_time - pause_time_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
*elapsed_time = actual_elapsed;
|
||||||
|
*hash_rate = (actual_elapsed > 0) ? (total_attempts / actual_elapsed) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -170,7 +184,26 @@ EMSCRIPTEN_KEEPALIVE
|
||||||
#endif
|
#endif
|
||||||
void stop_mining()
|
void stop_mining()
|
||||||
{
|
{
|
||||||
keep_running = 0;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -209,6 +242,8 @@ void reset_mining()
|
||||||
total_attempts = 0;
|
total_attempts = 0;
|
||||||
coins_found = 0;
|
coins_found = 0;
|
||||||
found_coins_count = 0;
|
found_coins_count = 0;
|
||||||
|
pause_time_offset = 0;
|
||||||
|
last_pause_time = 0;
|
||||||
mining_start_time = get_time();
|
mining_start_time = get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
139
index.html
139
index.html
|
|
@ -6,6 +6,8 @@
|
||||||
body {
|
body {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
|
|
@ -17,6 +19,24 @@
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
#coins-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
#coins {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.control-group {
|
.control-group {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
|
|
@ -25,6 +45,17 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
h2 {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.coin-entry {
|
||||||
|
color: #006400;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.coin-data {
|
||||||
|
color: #000080;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -40,16 +71,25 @@
|
||||||
<button id="start">Start Mining</button>
|
<button id="start">Start Mining</button>
|
||||||
<button id="stop">Stop Mining</button>
|
<button id="stop">Stop Mining</button>
|
||||||
<button id="reset">Reset</button>
|
<button id="reset">Reset</button>
|
||||||
|
<button id="clearCoins">Clear Coins Display</button>
|
||||||
|
|
||||||
<div id="stats">
|
<div id="stats">
|
||||||
Waiting to start...
|
Waiting to start...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="aad_coin_miner_wasm.js"></script>
|
<div id="coins-container">
|
||||||
|
<h2>Found Coins (<span id="coin-count">0</span>)</h2>
|
||||||
|
<div id="coins"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="coin_miner_wasm.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let mining = false;
|
let mining = false;
|
||||||
let Module;
|
let Module;
|
||||||
let miningInterval;
|
let miningInterval;
|
||||||
let updateInterval;
|
let updateInterval;
|
||||||
|
let lastDisplayedCoinCount = 0;
|
||||||
|
let pausedStats = false;
|
||||||
|
|
||||||
CoinMinerModule().then(mod => {
|
CoinMinerModule().then(mod => {
|
||||||
Module = mod;
|
Module = mod;
|
||||||
|
|
@ -58,6 +98,8 @@
|
||||||
document.getElementById('start').onclick = () => {
|
document.getElementById('start').onclick = () => {
|
||||||
if (!mining) {
|
if (!mining) {
|
||||||
mining = true;
|
mining = true;
|
||||||
|
Module._resume_mining();
|
||||||
|
pausedStats = false;
|
||||||
console.log('Starting mining...');
|
console.log('Starting mining...');
|
||||||
startMining();
|
startMining();
|
||||||
}
|
}
|
||||||
|
|
@ -68,27 +110,111 @@
|
||||||
Module._stop_mining();
|
Module._stop_mining();
|
||||||
clearInterval(miningInterval);
|
clearInterval(miningInterval);
|
||||||
clearInterval(updateInterval);
|
clearInterval(updateInterval);
|
||||||
|
|
||||||
|
updateStats();
|
||||||
|
|
||||||
|
let currentHTML = document.getElementById('stats').innerHTML;
|
||||||
|
document.getElementById('stats').innerHTML = currentHTML.replace('Mining Statistics:', 'Mining Statistics (PAUSED):');
|
||||||
|
|
||||||
|
pausedStats = true;
|
||||||
|
|
||||||
console.log('Mining stopped');
|
console.log('Mining stopped');
|
||||||
};
|
};
|
||||||
|
|
||||||
document.getElementById('reset').onclick = () => {
|
document.getElementById('reset').onclick = () => {
|
||||||
Module._reset_mining();
|
Module._reset_mining();
|
||||||
mining = false;
|
mining = false;
|
||||||
|
pausedStats = false;
|
||||||
clearInterval(miningInterval);
|
clearInterval(miningInterval);
|
||||||
clearInterval(updateInterval);
|
clearInterval(updateInterval);
|
||||||
|
lastDisplayedCoinCount = 0;
|
||||||
document.getElementById('stats').innerHTML = 'Reset complete. Click Start to begin.';
|
document.getElementById('stats').innerHTML = 'Reset complete. Click Start to begin.';
|
||||||
|
document.getElementById('coins').innerHTML = '';
|
||||||
|
document.getElementById('coin-count').textContent = '0';
|
||||||
console.log('Mining reset');
|
console.log('Mining reset');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
document.getElementById('clearCoins').onclick = () => {
|
||||||
|
document.getElementById('coins').innerHTML = '';
|
||||||
|
console.log('Coins display cleared');
|
||||||
|
};
|
||||||
|
|
||||||
|
function coinToString(coinPtr) {
|
||||||
|
let coinStr = '';
|
||||||
|
for (let i = 0; i < 55; i++) {
|
||||||
|
const byteIdx = i ^ 3;
|
||||||
|
const wordIdx = Math.floor(byteIdx / 4);
|
||||||
|
const byteInWord = byteIdx % 4;
|
||||||
|
|
||||||
|
const word = Module.getValue(coinPtr + wordIdx * 4, 'i32');
|
||||||
|
const byte = (word >> (byteInWord * 8)) & 0xFF;
|
||||||
|
|
||||||
|
if (byte >= 32 && byte <= 126) {
|
||||||
|
coinStr += String.fromCharCode(byte);
|
||||||
|
} else if (byte === 10) {
|
||||||
|
coinStr += '\\n';
|
||||||
|
} else if (byte === 0x80) {
|
||||||
|
coinStr += '[0x80]';
|
||||||
|
} else {
|
||||||
|
coinStr += `[0x${byte.toString(16).padStart(2, '0')}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return coinStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayNewCoins() {
|
||||||
|
const totalCoins = Module._get_found_coins_count();
|
||||||
|
|
||||||
|
if (totalCoins > lastDisplayedCoinCount) {
|
||||||
|
const coinsDiv = document.getElementById('coins');
|
||||||
|
|
||||||
|
for (let i = lastDisplayedCoinCount; i < totalCoins; i++) {
|
||||||
|
const coinPtr = Module._get_found_coin(i);
|
||||||
|
if (coinPtr !== 0) {
|
||||||
|
const coinStr = coinToString(coinPtr);
|
||||||
|
const timestamp = new Date().toLocaleTimeString();
|
||||||
|
|
||||||
|
const entry = document.createElement('div');
|
||||||
|
entry.innerHTML = `<span class="coin-entry">[${timestamp}] Coin #${i + 1}:</span> <span class="coin-data">${coinStr}</span>`;
|
||||||
|
coinsDiv.appendChild(entry);
|
||||||
|
|
||||||
|
coinsDiv.scrollTop = coinsDiv.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDisplayedCoinCount = totalCoins;
|
||||||
|
document.getElementById('coin-count').textContent = totalCoins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateStats() {
|
function updateStats() {
|
||||||
const attemptsPtr = Module._malloc(8);
|
const attemptsPtr = Module._malloc(8);
|
||||||
const coinsPtr = Module._malloc(4);
|
const coinsPtr = Module._malloc(4);
|
||||||
const hashRatePtr = Module._malloc(8);
|
const hashRatePtr = Module._malloc(8);
|
||||||
const elapsedPtr = Module._malloc(8);
|
const elapsedPtr = Module._malloc(8);
|
||||||
|
|
||||||
|
// Zero-initialize the memory before calling
|
||||||
|
Module.setValue(attemptsPtr, 0, 'i32');
|
||||||
|
Module.setValue(attemptsPtr + 4, 0, 'i32');
|
||||||
|
|
||||||
Module._get_statistics(attemptsPtr, coinsPtr, hashRatePtr, elapsedPtr);
|
Module._get_statistics(attemptsPtr, coinsPtr, hashRatePtr, elapsedPtr);
|
||||||
|
|
||||||
const attempts = Module.getValue(attemptsPtr, 'i64');
|
// Read 64-bit unsigned value correctly
|
||||||
|
// On little-endian, low 32 bits come first
|
||||||
|
const attemptsLowUnsigned = Module.getValue(attemptsPtr, 'i32') >>> 0;
|
||||||
|
const attemptsHighUnsigned = Module.getValue(attemptsPtr + 4, 'i32') >>> 0;
|
||||||
|
|
||||||
|
// Combine - for display purposes, if high part is 0, just show low part
|
||||||
|
let attempts;
|
||||||
|
if (attemptsHighUnsigned === 0) {
|
||||||
|
attempts = attemptsLowUnsigned;
|
||||||
|
} else {
|
||||||
|
// Use BigInt for values > 32 bits
|
||||||
|
const low = BigInt(attemptsLowUnsigned);
|
||||||
|
const high = BigInt(attemptsHighUnsigned);
|
||||||
|
attempts = (high * BigInt(4294967296)) + low;
|
||||||
|
}
|
||||||
|
|
||||||
const coins = Module.getValue(coinsPtr, 'i32');
|
const coins = Module.getValue(coinsPtr, 'i32');
|
||||||
const hashRate = Module.getValue(hashRatePtr, 'double');
|
const hashRate = Module.getValue(hashRatePtr, 'double');
|
||||||
const elapsed = Module.getValue(elapsedPtr, 'double');
|
const elapsed = Module.getValue(elapsedPtr, 'double');
|
||||||
|
|
@ -103,20 +229,16 @@
|
||||||
Attempts: ${attempts.toString()}<br>
|
Attempts: ${attempts.toString()}<br>
|
||||||
Coins Found: ${coins}<br>
|
Coins Found: ${coins}<br>
|
||||||
Hash Rate: ${(hashRate / 1e6).toFixed(2)} MH/s<br>
|
Hash Rate: ${(hashRate / 1e6).toFixed(2)} MH/s<br>
|
||||||
Elapsed Time: ${elapsed.toFixed(2)} seconds<br>
|
Elapsed Time: ${elapsed.toFixed(2)} seconds
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const coinsFound = Module._get_found_coins_count();
|
displayNewCoins();
|
||||||
if (coinsFound > 0) {
|
|
||||||
console.log(`Total coins found: ${coinsFound}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function startMining() {
|
function startMining() {
|
||||||
const batchSize = parseInt(document.getElementById('batchSize').value);
|
const batchSize = parseInt(document.getElementById('batchSize').value);
|
||||||
const updateMs = parseInt(document.getElementById('updateInterval').value);
|
const updateMs = parseInt(document.getElementById('updateInterval').value);
|
||||||
|
|
||||||
// Mine continuously using setInterval for larger batches
|
|
||||||
miningInterval = setInterval(() => {
|
miningInterval = setInterval(() => {
|
||||||
if (!mining) {
|
if (!mining) {
|
||||||
clearInterval(miningInterval);
|
clearInterval(miningInterval);
|
||||||
|
|
@ -125,7 +247,6 @@
|
||||||
Module._mine_coins_wasm(batchSize);
|
Module._mine_coins_wasm(batchSize);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
// Update stats periodically
|
|
||||||
updateInterval = setInterval(updateStats, updateMs);
|
updateInterval = setInterval(updateStats, updateMs);
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|
|
||||||
3
makefile
3
makefile
|
|
@ -43,6 +43,7 @@ clean:
|
||||||
rm -f sha1_tests
|
rm -f sha1_tests
|
||||||
rm -f sha1_cuda_test sha1_cuda_kernel.cubin
|
rm -f sha1_cuda_test sha1_cuda_kernel.cubin
|
||||||
rm -f coin_miner_cpu coin_miner_simd coin_miner_cuda coin_miner_cuda_kernel.cubin
|
rm -f coin_miner_cpu coin_miner_simd coin_miner_cuda coin_miner_cuda_kernel.cubin
|
||||||
|
rm -f coin_miner_wasm.js coin_miner_wasm.wasm
|
||||||
rm -f benchmark
|
rm -f benchmark
|
||||||
rm -f a.out
|
rm -f a.out
|
||||||
|
|
||||||
|
|
@ -85,7 +86,7 @@ coin_miner_cuda: aad_coin_miner_cuda.c coin_miner_cuda_kernel.cubin aad_sha1.h a
|
||||||
cc -march=native -Wall -Wshadow -Werror -O3 -I$(CUDA_DIR)/include $< -o $@ -lcuda
|
cc -march=native -Wall -Wshadow -Werror -O3 -I$(CUDA_DIR)/include $< -o $@ -lcuda
|
||||||
|
|
||||||
coin_miner_wasm: aad_coin_miner_wasm.c aad_sha1.h aad_sha1_cpu.h aad_sha1_wasm.h aad_data_types.h aad_utilities.h aad_vault.h makefile
|
coin_miner_wasm: aad_coin_miner_wasm.c aad_sha1.h aad_sha1_cpu.h aad_sha1_wasm.h aad_data_types.h aad_utilities.h aad_vault.h makefile
|
||||||
emcc -O3 -flto -o aad_coin_miner_wasm.js aad_coin_miner_wasm.c \
|
emcc -O3 -flto -o coin_miner_wasm.js aad_coin_miner_wasm.c \
|
||||||
-s WASM=1 \
|
-s WASM=1 \
|
||||||
-s EXPORTED_FUNCTIONS='["_mine_coins_wasm","_get_statistics","_stop_mining","_reset_mining","_get_found_coin","_get_found_coins_count","_malloc","_free"]' \
|
-s EXPORTED_FUNCTIONS='["_mine_coins_wasm","_get_statistics","_stop_mining","_reset_mining","_get_found_coin","_get_found_coins_count","_malloc","_free"]' \
|
||||||
-s EXPORTED_RUNTIME_METHODS='["cwrap","ccall","getValue","setValue"]' \
|
-s EXPORTED_RUNTIME_METHODS='["cwrap","ccall","getValue","setValue"]' \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue