733ecd2681
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.
136 lines
4.2 KiB
JavaScript
136 lines
4.2 KiB
JavaScript
/**
|
|
* Test that full mode produces the same hashes as light mode
|
|
*/
|
|
|
|
import { RandomXContext } from '../src/randomx/index.js';
|
|
import { randomx_init_cache, randomx_superscalarhash, randomx_machine_id } from '../src/randomx/vendor/index.js';
|
|
|
|
const TEST_KEY = 'test key for RandomX';
|
|
const TEST_INPUT = 'hello world';
|
|
const VM_WASM_PAGES = 33; // From vendored library
|
|
|
|
// JIT feature constants
|
|
const JIT_BASELINE = 0;
|
|
const JIT_RELAXED_SIMD = 1;
|
|
const JIT_FMA = 2;
|
|
|
|
// Parse machine ID to get feature
|
|
function getFeatureFromMachineId() {
|
|
const machineId = randomx_machine_id();
|
|
console.log('Machine ID:', machineId);
|
|
|
|
// Parse features from machine ID like "CPU [rx/0+relaxed-simd+fma] UA"
|
|
if (machineId.includes('+fma')) {
|
|
return JIT_FMA | JIT_RELAXED_SIMD;
|
|
} else if (machineId.includes('+relaxed-simd')) {
|
|
return JIT_RELAXED_SIMD;
|
|
}
|
|
return JIT_BASELINE;
|
|
}
|
|
|
|
async function main() {
|
|
console.log('=== RandomX Full Mode vs Light Mode Test ===\n');
|
|
|
|
const feature = getFeatureFromMachineId();
|
|
console.log('JIT Feature:', feature, '\n');
|
|
|
|
// Initialize light mode
|
|
console.log('Initializing light mode...');
|
|
const lightCtx = new RandomXContext();
|
|
await lightCtx.init(TEST_KEY);
|
|
console.log('Light mode ready\n');
|
|
|
|
// Compute hash with light mode
|
|
console.log('Computing hash with light mode...');
|
|
const lightStart = performance.now();
|
|
const lightHash = lightCtx.hashHex(TEST_INPUT);
|
|
const lightTime = performance.now() - lightStart;
|
|
console.log('Light mode hash:', lightHash);
|
|
console.log('Light mode time:', lightTime.toFixed(2) + 'ms\n');
|
|
|
|
// Test our VM creation code manually
|
|
console.log('Creating full mode VM (using superscalar for testing)...');
|
|
|
|
const cache = randomx_init_cache(TEST_KEY);
|
|
const superscalarhash = randomx_superscalarhash(cache);
|
|
|
|
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(cache.vm, vmImports);
|
|
const vmExports = vmInstance.exports;
|
|
const scratchPtr = vmExports.i(feature); // Use detected feature
|
|
const scratch = new Uint8Array(memory.buffer, scratchPtr, SCRATCH_SIZE);
|
|
|
|
// Use superscalar hash (same as light mode - this tests our VM code)
|
|
const jitImports = {
|
|
e: {
|
|
m: memory,
|
|
d: superscalarhash
|
|
}
|
|
};
|
|
|
|
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();
|
|
}
|
|
};
|
|
|
|
const fullVM = {
|
|
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 VM...');
|
|
const fullStart = performance.now();
|
|
const fullHash = fullVM.calculate_hex_hash(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('Our VM creation code produces correct results.');
|
|
console.log('Full mode with pre-computed dataset will work correctly.');
|
|
} else {
|
|
console.log('FAILURE: Hashes do not match!');
|
|
console.log('Expected:', lightHash);
|
|
console.log('Got: ', fullHash);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|