Releases: trusts-stack-network/tsn
v2.3.6 — Anti-spam, fork recovery, snapshot auto-trigger
Summary
Hotfix release addressing network stability under the combined pressure of
stale peers, broken fork-work computation, and cascading auto-wipes. After
this release the mesh no longer destroys itself when a peer serves an old
snapshot, and outdated peers are soft-banned at the HTTP layer instead of
flooding logs.
Changes
Anti-spam middleware (sync routes)
- Per-IP escalating ban (1h / 6h / 24h) for peers presenting outdated
X-TSN-Version, wrongX-TSN-Network, or wrongX-TSN-Genesisheaders. - Ban triggers after 3 offenses in a sliding window.
- WARN log deduplicated per-IP on a 5-minute window to prevent log flood.
- Missing headers pass through (internal HTTP callers are not always header-aware).
- Outbound
/tipand/blocksrequests now include Network + Genesis headers.
Fork-work recovery fix
calculate_chain_worknow adds a bounded prefix estimate drawn from local
cumulative work when the walk back from a fork tip cannot reach a
known-work ancestor, guarded byMAX_REORG_DEPTHto reject long-range
attacks. Previously, valid longer chains were rejected with
REJECT LESS_WORKbecause the accumulated difficulty was under-counted.
Auto-wipe disabled in watchdog
- Height-stuck, peers-far-ahead, solo-fork, and resync-loop signals are now
log-only. Operator triggers re-sync manually via/admin/force-resync.
Stops the cascade of self-destructive wipes that followed transient mesh
instabilities and re-imported stale snapshots.
No wipe on rollback-below-finalization
- When a peer proposes a fork that would require rolling past our finalized
height, the peer is rejected instead of wiping our chain. Finalized blocks
are canonical.
Snapshot auto-trigger fix
- The first snapshot now fires at h=1100 as intended, not at h=2100.
- Also fixes: after a restart above the interval boundary, the node triggers
its first snapshot on the next block accepted.
Snapshot cache staleness
- HTTP snapshot cache is now also invalidated when it is more than 500
blocks behind the current tip, not only when it is ahead (rollback case).
MINIMUM_VERSION = 2.3.6
- Community nodes on 2.3.3 / 2.3.4 / 2.3.5 are rejected at the HTTP sync
layer. Auto-update pulls 2.3.6 within five minutes on nodes that have it
enabled.
Compatibility
- Network:
tsn-testnet-v5 - Genesis:
dadfa2a3f3690038b8efc3bc4e6b647719081393b100a106101c8e11864ed4b1 - No consensus change, no schema change, no migration.
Binary
tsn-2.3.6-linux-x86_64.tar.gz- SHA256:
44767e18b2c017686d2c8e1ee903d424f6f6c7dec2ac0ef2a4093c022a3a0f45 - Signature verified via latest.json manifest.
- SHA256:
Tests
- 394 library tests pass.
- End-to-end validated on live testnet-v5 (5 seeds, rolling deploy, snapshot
cross-confirmation, GitHub snapshot mirror publish).
v2.3.5 — testnet-v5 reset
TESTNET RESET
This release resets the chain to testnet-v5. All nodes on v2.3.4 or earlier must upgrade. Old blockchain data is auto-wiped on first boot (genesis hash mismatch). Wallets are preserved but their old notes are archived (the pre-reset chain is gone).
Why
On April 19 a chain split left nodes on incompatible forks (Chain A at h=8600+ with zero real activity, Chain B stuck at h=7700 finalized). Neither could reconcile without rolling back below finalization. This release cuts the knot by rolling out a new genesis that makes the split moot — every node goes back to h=0 on a single, clean chain.
What's in 2.3.5
- Network identity:
tsn-testnet-v4→tsn-testnet-v5,MINIMUM_VERSIONbumped to 2.3.5 so pre-v2.3.5 peers are refused, new genesis hashdadfa2a3f369... - Auto-wipe: obsolete
blockchain/andsnapshots/directories are cleared on boot when the genesis no longer matches - Wallet obsolescence:
scan_stategets anetwork_namecolumn; a wallet recorded against an old testnet has its notes archived and scan cursor reset on open (keys preserved, address unchanged) - Fast-sync peer verification: a peer advertising a different
genesis_hashis rejected as being on an incompatible network — a v2.3.4 snapshot cannot be re-adopted onto v2.3.5 by accident - CLOSE-WAIT fix: the P2P mempool cleanup introduced in v2.3.4 no longer starves axum's accept loop under external
/tippolling load ./tsn balance429 behaviour: best-effort orphan detection bails after two consecutive rate-limit errors instead of waiting minutes; 100ms pacing between position queries- Snapshot GitHub mirror: seeds with
TSN_SNAPSHOT_GH_TOKENset publish signed snapshots totrusts-stack-network/tsn-snapshotsassnapshot-<height>releases; last 10 kept, older ones pruned
Upgrading
- Seeds auto-upgrade on their next 5-minute cycle (
latest.jsonwill be bumped). - Miners on v2.3.4 or earlier are rejected by
MINIMUM_VERSION— must re-download the binary. - Wallets: nothing to do. Balance may show zero until the new chain produces blocks containing your payouts.
Verification
sha256(tsn-2.3.5-linux-x86_64.tar.gz)listed inlatest.jsonathttps://tsnchain.com/releases/latest.json- Ed25519 signature is over the raw 32-byte SHA256 digest; verifying key is hardcoded in
src/network/auto_update.rs - Tests: 394 library + 13 binary pass; local stress test sustains 12000 req/s with 0 CLOSE-WAIT accumulation
v2.3.4
Highlights
- P2P mempool cleanup: the GossipSub NewBlock path now removes confirmed transactions and spent nullifiers from the local mempool, matching the HTTP
receive_blockbehaviour. Miners that ingest blocks only via P2P no longer loop onNullifier already spentwhile other miners extend the chain. - Snapshot disk persistence: auto-snapshots are written to
<data_dir>/snapshots/(compressed blob + signed manifest) with a 24h retention policy, so they survive process restarts instead of being lost when the cache in RAM is cleared. - Wallet orphan visibility:
tsn balancenow pre-validates each unspent note's witness against the node's Merkle tree and reportsTotal / Spendable / Stuck, so orphan notes from a chain reorg are surfaced before a send attempt. - Consolidation wait back to 180s: the prior 600s timeout was a workaround for the stale mempool bug above. With the cleanup fix in place, 180s is sufficient again.
Sanity checks
- 394 library tests + 13 binary tests pass (incl. two new
persist_snapshot_to_diskround-trip tests). - Light-client smoke test against the live network accepts new P2P blocks cleanly.
v2.3.3
v2.3.3 — pre-validate unspent note witnesses before send
Linux x86_64 binary only. Other platforms can be built from source with cargo build --release.
Fix
Adds pre_validate_orphan_positions, a helper called at the top of cmd_send that queries the node for every unspent note's Merkle leaf and flags the ones whose stored pq_commitment no longer matches. Orphan notes are now excluded from the very first batch instead of being discovered round-by-round via proof failure.
This addresses the root cause of the v2.3.1 observation that notes become silently orphan after chain reorgs. The proper long-term fix is a reorg-aware partial re-scan at scan time; this release ships the reactive counterpart that runs before each send — enough to unblock users whose wallets accumulated orphan dust.
New CLI output
Balance 1149.9990 TSN
Sending 200.0000 TSN to 205190d1...
Fee 0.0010 TSN
Validating 17 note witness(es)... done (17 checked, 5 orphan(s) detected)
Spendable 460.0000 TSN (5 orphan note(s) excluded, 689.9990 TSN stuck)
Notes 5 selected (230.0000 TSN, change: 29.9990 TSN)
Proof generating... done
Submit confirmed!
TX: fc2d91efa033f57774223a48751006d7fa72afc017b41be33a969557f72e413d
Total send time: 6 seconds vs minutes of retry loops in v2.3.1 when the wallet had many orphans.
If the spendable balance is below the requested amount+fee, the send bails immediately with a clear error pointing to the rescan menu.
Compatibility
No consensus change. No schema change. No migration. MINIMUM_VERSION unchanged at 2.2.0. All 11 resolve_pq_commitment unit tests still pass.
Verification
SHA256 (tarball): $(cat /root/tsn-v233/tsn-2.3.3-linux-x86_64.tar.gz.sha256 | awk '{print $1}')
Ed25519-signed via the hardcoded RELEASE_SIGNING_PUBKEY. Auto-update will pick this up on the 5-minute cycle.
v2.3.2
v2.3.2 — wallet rescan actually deletes rows + operational fixes
Linux x86_64 binary only — macOS and Windows binaries are not built for this release. Users on those platforms can build from source with cargo build --release.
Includes everything from v2.3.1 (Merkle witness orphan detection, HTTP 429 backoff, auto-consolidation refactor, admin mempool purge endpoint, mempool diagnostic logs) plus three additional fixes:
Wallet
- Rescan actually clears the database. The interactive "Rescan wallet" menu and
POST /wallet/rescanused to report success while leaving the SQLite wallet.db untouched. They now DELETE the rows so a rescan genuinely starts from height 0. tsn sendfails fast with an actionable error when the wallet file is already locked by another process (typically a running miner on the same wallet). Previously it would hang forever with no output.
Operational
- Metrics server auto-fallback across ports 9091–9099 when 9090 is taken. Running a miner and a relay on the same host no longer logs "Address already in use" noise on the second process.
From v2.3.1 (included)
- Merkle witness orphan detection in the send path. Notes whose leaf no longer matches the server Merkle tree (typically after a reorg) are caught before proving and skipped from the batch. Auto-consolidation no longer dies on a single stale note.
- Exponential backoff (1s, 2s, 4s, 8s, 16s, 32s) on HTTP 429 for witness fetch and tx submit.
- Gossipsub history raised to 600 heartbeats so v2 transactions reliably reach miners behind high-latency mesh peers.
- Private-IP filter on peer Identify messages.
- Tip / block / fork-recovery deduplication via LRU caches.
- New loopback-only admin endpoint
POST /admin/mempool/purge. - Diagnostic warn logs in
mempool.add_v2for every reject path.
Compatibility
No consensus change. No schema change. No migration. MINIMUM_VERSION unchanged at 2.2.0.
Verification
SHA256: 32928810ac1d31ea5026f5e51194fedcbaabca187a48e3418dace92b614d1621
All 11 new wallet unit tests pass.
v2.2.1 — Fix wallet auto-detection after migration
Bug fix
After v2.2.0 migrates wallet.json to wallet.db, the auto-detection on restart only searched for .json files and could not find the migrated wallet. This caused a new wallet to be created on restart, losing access to the previous one.
Fix
auto_detect_wallet() now searches for wallet.db first, falls back to wallet.json. Applies to all node roles (miner, relay, light client).
Upgrade
Download the binary and replace your current one. The auto-update system will also pick this up automatically.
If you were affected: your original wallet is safe — it was renamed to wallet.json.migrated during v2.2.0 migration. The wallet.db file contains all your notes. Simply update to v2.2.1 and restart.
v2.2.0 — Wallet Rewrite (SQLite)
Wallet Rewrite — SQLite Persistence
Replaces the fragile wallet.json with a crash-safe SQLite WAL database.
Fixes the balance-reset-on-restart bug reported by community miners.
What changed
- SQLite WAL wallet — crash-safe, concurrent-reader support, automatic migration from JSON
- Atomic file writes — write to temp file then rename (prevents corruption on crash)
- File locking (flock) — prevents concurrent processes from corrupting wallet data
- Wallet API endpoints —
GET /wallet/balance,/wallet/history,/wallet/address,POST /wallet/scan,/wallet/rescan - WalletService — thread-safe wallet access shared between mining loop and API
- Graceful shutdown — Ctrl+C flushes SQLite WAL before exit
- Error logging — all silent
.ok()calls replaced withtracing::error - Genesis hash locked for testnet-v4
- MINIMUM_VERSION raised to 2.2.0
Migration
Automatic. On first run, your existing wallet.json is migrated to wallet.db.
The original file is preserved as wallet.json.migrated (not deleted).
Network
- Network:
tsn-testnet-v4(fresh chain) - Genesis:
bf18bbaad9d19045abb926425f652dffb84a9bf010a9555cd863d7b1e08ca539 - 6 nodes running, all synced
Verification
- 386/386 tests pass
- Migration verified on real wallets (978 notes / 44988 TSN)
- Restart persistence confirmed on 6-node live network
v2.1.6
Mining
- Block confirmation:
Potential mined blockon mine, thenCONFIRMEDorORPHANEDafter 12s network check - New
addressconsole command to display mining wallet address
Sync
- Improved fast-sync blind zone handling
- Stale blocks cleared from DB during legitimate chain reset
- Patch D exception for genesis-level work
Network
- MINIMUM_VERSION = 2.1.6
- Testnet v3 — fresh chain from genesis
- Full English codebase
Upgrade instructions
- Download the binary
- Stop your node
- Delete blockchain data:
rm -rf data-miner/blockchainorrm -rf data/blockchain - Restart with the new binary
v2.1.5 — Mining Efficiency & Observability
v2.1.5 — Mining Efficiency & Observability
Mining & Sync
- Fork recovery path shortened from 6 retries to 2 retries per divergence event (67% reduction in wasted sync cycles)
- Wasted retry time reduced from ~12.5s to ~2.5s per fork recovery event (~10 seconds saved per event)
- Average fork recovery latency: 43ms (new instrumented metric)
- New
GET /mining/metricsAPI endpoint: real-time counters for empty_batches, stale_blocks, fork_recoveries, recovery_time_ms, reorg_count, orphan_count
Wallet
restore-wallet --seedCLI command: deterministic wallet recovery from 24-word seed phrasenew-walletnow derives keys from the displayed seed phrase via PBKDF2-SHA256 (210k iterations) + ML-DSA-65 deterministic keygen- Web wallet: removed misleading balance display (scan without viewing key no longer shows unverified totals)
- Web wallet: removed faucet (not applicable to live chain)
Snapshots
- Automatic block-based snapshot trigger: exports signed snapshot when a new multiple of 1000 blocks becomes finalized
- Cross-confirmation from seed nodes runs automatically after each export
Logging
- Verbose sync messages (PROCESS_ORPHANS, SYNC_BATCH, fork detection) moved from WARN to DEBUG
- libp2p gossipsub duplicate message warnings filtered
- P2P peer identification moved to DEBUG
- Stale mining and natural reorgs logged at appropriate levels
Network
- Auto-update URL corrected to new repository
- MINIMUM_VERSION: 2.1.5
- All source code comments and log messages in English
Commitment Root (instrumentation only)
- COMMITMENT_ROOT_MISMATCH warnings now include full diagnostic payload: pre/post PQ tree size, fast_sync offsets, expected vs actual leaf insertions
- Block template logs PQ tree state for miner-side diagnostics
- Soft check retained — hard reject deferred until tree determinism is proven stable
v2.1.4 — Verified Snapshot System
What's New
Verified Snapshot System
- Ed25519 signed snapshot manifests with multi-seed cross-confirmation
restore-snapshotCLI — strict 4-step verification- 5 new snapshot API endpoints
- Public snapshot repository: tsn-snapshots
- Rolling 24h retention
Explorer
- Snapshots tab, P2P freshness tracking, miner PeerID identification
- Block toast notifications, TX deduplication
Network
- MINIMUM_VERSION = 2.1.4
- 1-hour stability observation: 13 checks, 0 failures