Files
salvium-rs/test/legacy-js/debug-superscalar-hash.js
Matt Hess 733ecd2681 Migrate all JS tests to Rust: 9-crate workspace, 703 tests, 0 JS remaining
Add root Cargo workspace with 9 crates: salvium-crypto (extended),
  salvium-types, salvium-consensus, salvium-wallet, salvium-tx,
  salvium-rpc, salvium-miner (extended), salvium-cli, salvium-multisig.

  New modules: chain_state, block_weight, alt_chain, validation,
  offline signing, stake lifecycle, wallet sync/query/encryption/utxo,
  randomx utilities, and full multisig crate with CARROT support.

  Delete 188 JS test/helper/debug files; archive integration test
  scripts to test/legacy-js/ for live testnet use. Testnet integration
  tests (transfer, stake, burn, convert, sweep) remain as #[ignore]-
  gated Rust tests runnable with --ignored against a live daemon.
2026-02-17 23:09:35 +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.');