Replace static fs/path imports with dynamic environment detection.
Node/Bun uses fs.readFile, browsers use fetch() with import.meta.url
resolution for bundler compatibility
Add 17 new provider-level functions (derivationToScalar, deriveViewTag,
ecdhDecodeFull, computeCarrotSpendPubkey, randomScalar, etc.) that
compose backend primitives. Rewire all consumer files to import through
the crypto provider. Only internal JS point serialization (pointFromBytes/
pointToBytes) and source implementation files retain direct imports.
Switch 16 consumer files from direct crypto imports to the switchable
crypto provider. setCryptoBackend('wasm') now accelerates all real
transaction building, output scanning, and key derivation end-to-end.
Source implementation files (keccak.js, ed25519.js, scanning.js, etc.)
keep direct imports to avoid circular dependencies.
Implement pedersen_commit, zero_commit, and gen_commitment_mask in Rust
with hardcoded H generator point. All 56 equivalence tests pass including
homomorphic property verification: commit(a,m) - zeroCommit(a) = m*G.
Phase 1: keccak256 and blake2b compiled from Rust via wasm-pack (23KB).
Provider pattern enables switching between JS and WASM backends at runtime
while keeping all existing JS crypto code intact. Equivalence tests confirm
byte-for-byte matching across all inputs. Benchmarks: keccak256 ~4.6x faster,
blake2b ~15x faster with WASM backend.
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