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.
120 lines
3.7 KiB
JavaScript
120 lines
3.7 KiB
JavaScript
#!/usr/bin/env bun
|
|
// Debug transaction byte structure - find correct RCT offset
|
|
|
|
import { createDaemonRPC } from '../src/rpc/index.js';
|
|
import { hexToBytes, bytesToHex } from '../src/address.js';
|
|
|
|
const daemon = createDaemonRPC({ url: 'http://seed01.salvium.io:19081', timeout: 30000 });
|
|
|
|
function decodeVarint(data, offset) {
|
|
let value = 0n;
|
|
let shift = 0n;
|
|
let bytesRead = 0;
|
|
|
|
while (offset + bytesRead < data.length) {
|
|
const byte = data[offset + bytesRead];
|
|
bytesRead++;
|
|
value |= BigInt(byte & 0x7f) << shift;
|
|
if ((byte & 0x80) === 0) break;
|
|
shift += 7n;
|
|
if (shift >= 70n) throw new Error('Varint overflow');
|
|
}
|
|
return { value: Number(value), bytesRead };
|
|
}
|
|
|
|
async function test() {
|
|
const txHash = 'a5e85d03e9200229a72fc3cfe94e5b139c8c2ad982dc3fd174898be63269e670';
|
|
|
|
const resp = await daemon.getTransactions([txHash], { decode_as_json: true });
|
|
const txData = resp.result?.txs?.[0];
|
|
const data = hexToBytes(txData.as_hex);
|
|
|
|
console.log('TX size:', data.length, 'bytes');
|
|
console.log('Daemon says: type=6, inputs=9, outputs=2\n');
|
|
|
|
let offset = 0;
|
|
|
|
// Version
|
|
const version = decodeVarint(data, offset);
|
|
console.log(`Version: ${version.value} at offset 0`);
|
|
offset += version.bytesRead;
|
|
|
|
// Unlock time
|
|
const unlockTime = decodeVarint(data, offset);
|
|
console.log(`Unlock time: ${unlockTime.value}`);
|
|
offset += unlockTime.bytesRead;
|
|
|
|
// Number of inputs
|
|
const numInputs = decodeVarint(data, offset);
|
|
console.log(`\nInputs: ${numInputs.value}`);
|
|
offset += numInputs.bytesRead;
|
|
|
|
// Skip inputs (simplified - just find pattern)
|
|
for (let i = 0; i < numInputs.value; i++) {
|
|
const inputType = data[offset++];
|
|
if (inputType === 0x02) { // txin_to_key
|
|
const amount = decodeVarint(data, offset);
|
|
offset += amount.bytesRead;
|
|
const numOffsets = decodeVarint(data, offset);
|
|
offset += numOffsets.bytesRead;
|
|
for (let j = 0; j < numOffsets.value; j++) {
|
|
const ko = decodeVarint(data, offset);
|
|
offset += ko.bytesRead;
|
|
}
|
|
offset += 32; // key image
|
|
}
|
|
}
|
|
|
|
console.log(`After inputs: offset ${offset}`);
|
|
|
|
// Number of outputs
|
|
const numOutputs = decodeVarint(data, offset);
|
|
console.log(`\nOutputs: ${numOutputs.value}`);
|
|
offset += numOutputs.bytesRead;
|
|
|
|
// Skip outputs
|
|
for (let i = 0; i < numOutputs.value; i++) {
|
|
const amount = decodeVarint(data, offset);
|
|
offset += amount.bytesRead;
|
|
const outputType = data[offset++];
|
|
if (outputType === 0x02) { // txout_to_key
|
|
offset += 32; // public key
|
|
} else if (outputType === 0x03) { // txout_to_tagged_key
|
|
offset += 32; // public key
|
|
offset += 1; // view tag
|
|
}
|
|
}
|
|
|
|
console.log(`After outputs: offset ${offset}`);
|
|
|
|
// Extra
|
|
const extraLen = decodeVarint(data, offset);
|
|
console.log(`\nExtra length: ${extraLen.value}`);
|
|
offset += extraLen.bytesRead;
|
|
offset += extraLen.value; // Skip extra bytes
|
|
|
|
console.log(`\n=== RCT section starts at offset ${offset} ===`);
|
|
console.log(`Remaining bytes: ${data.length - offset}`);
|
|
|
|
// Show first 50 bytes of RCT
|
|
console.log(`\nFirst 50 RCT bytes: ${bytesToHex(data.slice(offset, offset + 50))}`);
|
|
|
|
// Search for SAL marker from RCT start
|
|
let salOffset = -1;
|
|
for (let i = offset; i < Math.min(offset + 200, data.length - 4); i++) {
|
|
if (data[i] === 0x03 && data[i+1] === 0x53 && data[i+2] === 0x41 && data[i+3] === 0x4c) {
|
|
salOffset = i;
|
|
console.log(`\nFound SAL marker at offset ${i} (${i - offset} bytes into RCT)`);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (salOffset === -1) {
|
|
console.log('\nNo SAL marker found - checking raw RCT type byte');
|
|
const rawType = data[offset];
|
|
console.log(`Raw type byte at RCT start: 0x${rawType.toString(16)} (${rawType})`);
|
|
}
|
|
}
|
|
|
|
test().catch(console.error);
|