Exercises the complete transfer flow on the self-contained testnet:
UTXO selection, gamma-distribution decoy selection, ring member
fetching, buildTransaction with CLSAG signing, mempool submission,
block mining, and recipient wallet scanning.
Key changes:
- TestnetNode: global output index, spent key image tracking,
getOuts/getOutputDistribution/sendRawTransaction/isKeyImageSpent RPCs
- TestnetMiner: includes mempool user transactions in mined blocks
- Testnet.transfer(): end-to-end send from wallet to wallet
- WalletSync: fallback to JSON-based tx processing when as_hex unavailable
- 5 new tests covering transfer, change outputs, double-spend rejection
Build a fully functional in-memory blockchain for integration testing:
- TestnetNode: daemon RPC-compatible interface backed by in-memory chain
- TestnetMiner: block assembly with real RandomX PoW (difficulty 1)
- Miner TX construction ported from C++ construct_miner_tx()
- Testnet orchestrator with wallet creation, sync, and balance tracking
Fix CARROT output creation to match C++ reference implementation:
- Use keyed Blake2b with SpFixedTranscript format (was unkeyed)
- Use X25519 curve for ECDH and ephemeral pubkeys (was Ed25519)
- Use blinding factor k_a=1 for coinbase outputs (was hash-derived)
- Handle coinbase clear-text amounts and zeroCommit in scanner
- Add isCarrot flag to WalletOutput model and serialization
20 tests, 105 assertions covering legacy and CARROT coinbase outputs
across the hard fork boundary at testnet height 1100.
- Implement tclsagSign() with dual generators G and T
- Implement tclsagVerify() with matching equations
- Add 29 comprehensive tests for sign/verify round-trips
- Update AUDIT.md to reflect full RingCT completeness
- wallet.js: isCarrotEnabled() now uses sync height and network to
automatically determine CARROT status based on HF activation heights
- wallet.js: getHfVersion() derives version from sync height instead
of relying on manually set value
- wallet.js: Added _getNetworkId() to map network strings to NETWORK_ID
- Mainnet CARROT activates at height 334750, testnet/stagenet at 1100
- Falls back to stored _hfVersion when sync height is 0 (pre-sync)
- Create src/oracle.js with complete pricing record support
- Data structures: PricingRecord, AssetData, SupplyData (matching C++ pricing_record.h)
- DSA/ECDSA signature verification with mainnet/testnet public keys
- Conversion rate calculation with rounding (getConversionRate, getConvertedAmount)
- Slippage calculation (1/32 = 3.125%) with refund logic
- Pricing record validation (HF gates, timestamps, signatures)
- JSON serialization/parsing for oracle responses
- HTTP client for fetching pricing records from oracle server
- Add 66 unit tests in test/oracle.test.js
- Export oracle module from index.js
- Add buildAuditTransaction() in transaction.js
- Add createAuditTransaction() in wallet.js
- Change-is-zero requirement: all coins locked
- Coins return via protocol_tx after maturity
- 14 unit tests
- Only valid during AUDIT hard fork periods (HF v6, v8)
- Add buildConvertTransaction() in transaction.js
- Add createConvertTransaction() in wallet.js
- Oracle-priced conversion with 3.125% slippage
- SAL <-> VSD only (other pairs rejected)
- 15 unit tests + integration test
- Note: Gated at HF v255, not yet enabled on mainnet
STAKE transactions:
- Add buildStakeTransaction() for creating stake transactions
- Add createStakeTransaction() wallet API for staking SAL/SAL1
- Extend serializeTxPrefix() with Salvium-specific fields (txType,
amount_burnt, asset types, return address, protocol_tx_data)
- Support STAKE_LOCK_PERIOD from network config (21600 mainnet, 20 testnet)
CLSAG fixes:
- Fix challenge hash to include full ring data matching C++ implementation
- Update both signing and verification to use consistent hash format
- Implement BP+ verification using @noble/curves for Ed25519 ops
- MSM 256 points in ~420ms - mobile-friendly, no WASM needed
- Add verifyBulletproofPlus, verifyBulletproofPlusBatch, verifyRangeProof
- Add generator initialization with caching (Gi, Hi points)
- 24 new tests including performance benchmarks
- Update exports in index.js and package.json
- Bump version to 0.3.0