Files
salvium-rs/test/debug-superscalar-hash.js
T
Matt Hess 7730b6993f ● Add AssemblyScript WASM VM for RandomX full mode
- Create assembly/vm.ts with full RandomX VM implementation
    - 256 instructions, 2048 iterations per hash
    - Native u64/f64 operations in WebAssembly
    - Full mode dataset lookups (2GB pre-computed)

  - Update miner to use WASM VM for full mode
    - mining-worker-asm.js uses pre-compiled WASM
    - ~32 H/s per thread (4x faster than light mode)
    - 8 threads achieves ~260 H/s

  - Clean up redundant code
    - Remove mining-worker-full.js (old JIT approach)
    - Consolidate 'asm' mode into 'full' mode
2026-01-18 01:16:10 +00:00

84 lines
3.0 KiB
JavaScript

/**
* Debug: Compare superscalar program hash with C++ reference
*
* C++ Instruction struct layout (8 bytes):
* uint8_t opcode; // offset 0
* uint8_t dst; // offset 1
* uint8_t src; // offset 2
* uint8_t mod; // offset 3
* uint32_t imm32; // offset 4-7 (little-endian)
*
* Expected hash for program 0: d3a4a6623738756f77e6104469102f082eff2a3e60be7ad696285ef7dfc72a61
*/
import { blake2b } from '../src/blake2b.js';
import { Blake2Generator, generateSuperscalar, SuperscalarInstructionType } from '../src/randomx/superscalar.js';
function bytesToHex(bytes) {
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
}
// Serialize program to bytes matching C++ layout
function serializeProgram(prog) {
const bytes = new Uint8Array(prog.instructions.length * 8);
for (let i = 0; i < prog.instructions.length; i++) {
const instr = prog.instructions[i];
const offset = i * 8;
bytes[offset + 0] = instr.opcode & 0xff;
bytes[offset + 1] = instr.dst & 0xff;
bytes[offset + 2] = instr.src & 0xff;
bytes[offset + 3] = instr.mod & 0xff;
// imm32 as little-endian
const imm = instr.imm32 >>> 0;
bytes[offset + 4] = imm & 0xff;
bytes[offset + 5] = (imm >> 8) & 0xff;
bytes[offset + 6] = (imm >> 16) & 0xff;
bytes[offset + 7] = (imm >> 24) & 0xff;
}
return bytes;
}
console.log('=== Superscalar Program Hash Debug ===\n');
const key = new TextEncoder().encode('test key 000');
const gen = new Blake2Generator(key);
// Expected hashes from C++ tests.cpp
const expectedHashes = [
'd3a4a6623738756f77e6104469102f082eff2a3e60be7ad696285ef7dfc72a61',
'f5e7e0bbc7e93c609003d6359208688070afb4a77165a552ff7be63b38dfbc86',
'85ed8b11734de5b3e9836641413a8f36e99e89694f419c8cd25c3f3f16c40c5a',
'5dd956292cf5d5704ad99e362d70098b2777b2a1730520be52f772ca48cd3bc0',
'6f14018ca7d519e9b48d91af094c0f2d7e12e93af0228782671a8640092af9e5',
'134be097c92e2c45a92f23208cacd89e4ce51f1009a0b900dbe83b38de11d791',
'268f9392c20c6e31371a5131f82bd7713d3910075f2f0468baafaa1abd2f3187',
'c668a05fd909714ed4a91e8d96d67b17e44329e88bc71e0672b529a3fc16be47',
'99739351315840963011e4c5d8e90ad0bfed3facdcb713fe8f7138fbf01c4c94',
'14ab53d61880471f66e80183968d97effd5492b406876060e595fcf9682f9295'
];
// Generate and hash all 10 programs
let allMatch = true;
for (let progIdx = 0; progIdx < 10; progIdx++) {
const prog = generateSuperscalar(gen);
const progBytes = serializeProgram(prog);
const hash = blake2b(progBytes, 32);
const hashHex = bytesToHex(hash);
const match = hashHex === expectedHashes[progIdx];
console.log(`Program ${progIdx}: size=${prog.instructions.length.toString().padStart(3)} addrReg=${prog.addressRegister} hash=${hashHex.slice(0, 16)}... ${match ? '✓' : '✗'}`);
if (!match) {
allMatch = false;
console.log(` Expected: ${expectedHashes[progIdx]}`);
console.log(` Got: ${hashHex}`);
}
}
console.log();
console.log(allMatch ? 'All 10 program hashes match!' : 'Some program hashes do not match.');