Files
salvium-rs/test/legacy-js/test-full-mode-complete.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

158 lines
4.8 KiB
JavaScript

/**
* Test complete full mode implementation with small dataset
*/
import { RandomXContext } from '../src/randomx/index.js';
import { RandomXFullMode } from '../src/randomx/full-mode.js';
const TEST_KEY = 'test key for RandomX';
const TEST_INPUT = 'hello world';
// For testing, we'll use a reduced item count
const TEST_ITEM_COUNT = 1000; // Just 1000 items for quick testing
async function main() {
console.log('=== RandomX Full Mode Complete Test ===\n');
// Get light mode hash for comparison
console.log('Initializing light mode for reference...');
const lightCtx = new RandomXContext();
await lightCtx.init(TEST_KEY);
const lightHash = lightCtx.hashHex(TEST_INPUT);
console.log('Light mode reference hash:', lightHash, '\n');
// Test full mode with small dataset
console.log('Testing full mode with small dataset (' + TEST_ITEM_COUNT + ' items)...');
const fullMode = new RandomXFullMode();
// Override dataset item count for testing
const RANDOMX_DATASET_ITEM_COUNT = 34078719; // Full count
// Manually init to use reduced item count
const { randomx_init_cache, randomx_superscalarhash, randomx_machine_id } = await import('../src/randomx/vendor/index.js');
fullMode.cache = randomx_init_cache(TEST_KEY);
fullMode.ssHash = randomx_superscalarhash(fullMode.cache);
// Generate small dataset
console.log('Generating test dataset...');
fullMode.dataset = new BigInt64Array(TEST_ITEM_COUNT * 8);
for (let i = 0; i < TEST_ITEM_COUNT; i++) {
const item = fullMode.ssHash(BigInt(i));
const offset = i * 8;
for (let j = 0; j < 8; j++) {
fullMode.dataset[offset + j] = item[j];
}
}
console.log('Test dataset ready\n');
// Create VM with dataset lookup that falls back to superscalar for out-of-range indices
const dataset = fullMode.dataset;
const ssHash = fullMode.ssHash;
const datasetLookup = (itemIndex) => {
const idx = Number(itemIndex);
if (idx < TEST_ITEM_COUNT) {
const offset = idx * 8;
return [
dataset[offset],
dataset[offset + 1],
dataset[offset + 2],
dataset[offset + 3],
dataset[offset + 4],
dataset[offset + 5],
dataset[offset + 6],
dataset[offset + 7]
];
}
// Fall back to superscalar for items beyond our test range
return ssHash(itemIndex);
};
// Get machine feature
const machineId = randomx_machine_id();
let feature = 0;
if (machineId.includes('+fma')) feature = 3;
else if (machineId.includes('+relaxed-simd')) feature = 1;
// Create VM
const VM_WASM_PAGES = 33;
const SCRATCH_SIZE = 16 * 1024;
const memory = new WebAssembly.Memory({ initial: VM_WASM_PAGES, maximum: VM_WASM_PAGES });
const vmImports = { env: { memory } };
const vmInstance = new WebAssembly.Instance(fullMode.cache.vm, vmImports);
const vmExports = vmInstance.exports;
const scratchPtr = vmExports.i(feature);
const scratch = new Uint8Array(memory.buffer, scratchPtr, SCRATCH_SIZE);
const jitImports = {
e: {
m: memory,
d: datasetLookup
}
};
const hashFn = (input, isHex) => {
if (typeof input === 'string') {
input = new TextEncoder().encode(input);
}
vmExports.I(isHex);
if (input.length <= SCRATCH_SIZE) {
scratch.set(input);
vmExports.H(input.length);
} else {
let p = 0;
while (p < input.length) {
const chunk = input.subarray(p, p + SCRATCH_SIZE);
p += SCRATCH_SIZE;
scratch.set(chunk);
vmExports.H(chunk.length);
}
}
let jitSize;
while (true) {
jitSize = vmExports.R();
if (jitSize === 0) break;
const jitModule = new WebAssembly.Module(scratch.subarray(0, jitSize));
const jitInstance = new WebAssembly.Instance(jitModule, jitImports);
jitInstance.exports.d();
}
};
fullMode.vm = {
calculate_hash: (input) => {
hashFn(input, false);
return new Uint8Array(scratch.subarray(0, 32));
},
calculate_hex_hash: (input) => {
hashFn(input, true);
return new TextDecoder().decode(scratch.subarray(0, 64));
}
};
console.log('Full mode VM ready\n');
// Compute hash with full mode
console.log('Computing hash with full mode...');
const fullStart = performance.now();
const fullHash = fullMode.hashHex(TEST_INPUT);
const fullTime = performance.now() - fullStart;
console.log('Full mode hash: ', fullHash);
console.log('Full mode time: ', fullTime.toFixed(2) + 'ms\n');
// Compare
console.log('=== Comparison ===');
if (lightHash === fullHash) {
console.log('SUCCESS: Hashes match!');
console.log('Full mode implementation is working correctly.');
} else {
console.log('FAILURE: Hashes do not match!');
console.log('Expected:', lightHash);
console.log('Got: ', fullHash);
process.exit(1);
}
}
main().catch(console.error);