Releases: HiImRook/accessible-tpi-chain
Release list
v0.8.0 - Observer Period, Correlation Detection, and Integrity Scaffold
v0.8.0 - Observer Period, Correlation Detection, and Integrity Scaffold
Status: Released
What Changed
This release establishes the architectural foundation for Valid Blockchain's Sybil resistance system. Three new modules define the complete observer period pipeline from data collection through promotion decisioning, along with a full architectural specification document.
correlation.rs - scaffolded
Broadcast anchor collection, peer response sampling, passive RTT fingerprinting, cluster detection, and correlation window analysis. The data collection and analysis layer that drives the 90-day observer period.
behavioral_merit.rs - scaffolded
Operational identity, wallet continuity, signing cadence, and behavioral merit scoring. Derives merit entirely from on-chain and network-observable behavior with no external dependencies at mainnet.
integrity.rs - scaffolded
NodeIntegrityScore, FlagRecord, FlagPattern, promotion decisioning, group penalty logic, and historical flag lifecycle. Current confidence is recoverable with clean behavior. Historical flags are permanent.
docs/v0.8-correlation-spec.md
Full architectural specification for the observer period and correlation detection pipeline. Covers:
- Two-tier network model - observer pool open to all; validator pool requires 90-day behavioral accumulation
- Passive RTT geographic confidence and physics floor violation detection
- Heartbeat correlation detection across three vectors: broadcast arrival correlation, heartbeat synchronization, and reaction correlation
- FlagPattern cross-node behavioral matching for attacker profiling across identity rotations
- NodeIntegrityScore separating recoverable current confidence from permanent historical record
- BroadcastAnchor bounded ring buffer retention model satisfying Zero Footprint constraints
- Testnet vs mainnet implementation split
Security
- reqwest bumped 0.11 to 0.12 resolving h2 CVE RUSTSEC-2026-0258
Notes
- All three modules are scaffold only. Implementation begins after live testnet deployment is stable.
- correlation.rs, behavioral_merit.rs, and integrity.rs are valid-blockchain branch only. They are not part of private-network or main.
- 119 tests passing, CI clean.
Full Changelog: See CHANGELOG.md
Previous Release: valid/v0.7.6
v0.7.6 - Arweave Publication Validation
v0.7.6 - Arweave Publication Validation
Status: Released
What Changed
Arweave publication pipeline validated against live mainnet.
Two correctness bugs identified and fixed through live submission testing:
Signing field order was wrong:
- Previous order placed data_root and data_size at positions 4 and 5
- Arweave format 2 spec requires: format, owner, target, quantity, reward, anchor, tags, data_size, data_root
- Every prior submission would have been rejected at the signature verification step
data_root leaf hash was missing a SHA256 pass:
- Chunks were passed raw to leaf_hash() instead of pre-hashed
- Correct computation: leaf_hash(SHA256(chunk), offset)
- Matches arweave-js merkle.ts reference implementation
Additional improvements:
- Wallet loading now supports ARWEAVE_WALLET_PATH (file path) alongside ARWEAVE_JWK_JSON
- Wallet address logged at startup for verification
- Full POST /tx response body logged for observability
- data_root and tx_id logged before submission
- Standalone test binary added (src/bin/arweave_test.rs) for future mainnet validation runs
Live Validation Result
Real archive segment submitted to Arweave mainnet:
Transaction ID: 71o-aNdFvGGPEcIvK6b4MCFKQjS-FJD_-KAIKDeiKCA
View: https://arweave.net/71o-aNdFvGGPEcIvK6b4MCFKQjS-FJD_-KAIKDeiKCA
- data_root correctness confirmed against live network
- RSA-PSS signing path confirmed correct
- Inline upload confirmed sufficient — chunked upload not required at current segment sizes
- 200 OK on first successful submission
Notes
- Chunked upload remains deferred — not needed for current archive segment sizes
- The arweave_test binary is a development/validation tool, not part of node operation
- The background publisher loop in the running node will now correctly submit real segments
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.5
v0.7.5 - TLS Trust Hardening Scaffolding
v0.7.5 - TLS Trust Hardening Scaffolding
Status: Released
What Changed
TLS fingerprint pinning infrastructure is now in place.
This release introduces the config fields, helpers, and enforcement path needed for certificate-level peer trust. The scaffolding is operational — empty allowlist means trust all, populated allowlist enforces pinning on every outbound connection including broadcasts.
Config:
- trusted_peer_fingerprints — optional SHA-256 fingerprint allowlist in config.toml
- tls_trust_mode — validated at startup; unsupported modes exit immediately
- Empty list = trust all, backward compatible with all existing deployments
tls.rs:
- validate_peer_certificate() — shared cert extraction and trust check used by all outbound paths
- is_trusted_fingerprint() — case-insensitive, whitespace-tolerant matching
- LoggingOnlyVerifier replaces FingerprintVerifier — name reflects actual behavior
network.rs:
- connect_and_handle_peer() enforces fingerprint allowlist after TLS handshake
- broadcast_message() enforces fingerprint allowlist — broadcast path no longer bypasses trust policy
Test coverage:
- 12 TLS trust tests covering fingerprint matching, case normalization, whitespace tolerance, cert extraction, empty allowlist, trusted and untrusted cert scenarios
- 119 total tests passing
Notes
- This is application-level trust scaffolding, not full mTLS
- LoggingOnlyVerifier accepts all certs at the rustls layer — trust enforcement runs after handshake via validate_peer_certificate()
- Ephemeral certs regenerate at startup — fingerprints must be exchanged out-of-band per session
- Persistent validator identity key and session-stable cert pinning deferred to future hardening
- Peer identity model (peer_addr_hash) remains completely untouched
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.4
v0.7.4 - Network Abuse Hardening
v0.7.4 - Network Abuse Hardening
Status: Released
What Changed
Two new rate limiting layers protect the network from abuse.
Connection rate limiting:
- Inbound connections tracked per source IP using a rolling 60-second window
- More than 5 attempts from the same IP within the window are dropped before TLS handshake
- Keyed by IP only — ephemeral port rotation does not bypass the limit
Message rate limiting:
- Per-peer inbound message budget of 100 messages per 10-second window
- Handshake counts against the budget — rate-limited peers disconnected immediately
- Rate check runs before update_seen() — abusive messages do not mutate peer liveness state
- Message history migrated during peer hash normalization with stale entry pruning
- cleanup_stale_peers() removes message history alongside peer and dial entries
Handshake validation hardening:
- PeerManager::apply_handshake_metadata() extracts handshake policy from main.rs into a testable helper
- Invalid their_addr now rejects all handshake data — gossip and RPC are ignored entirely when the sender's identity is malformed
- Gossiped peer addresses validated via is_valid_peer_addr() before entering PeerManager
- RPC addresses validated after canonicalization — invalid normalized RPC endpoints are not bound
- split_host_port() rejects empty bracketed hosts — []:8000 now correctly rejected
Test coverage:
- 7 rate limiting tests
- 23 handshake validation and address parser tests
- 107 total tests passing
Notes
- Rate limiting is first-pass minimal — no persistent banlists, subnet heuristics, or type-specific quotas
- Connection limiter state does not prune empty IP entries — acceptable for v0.7.4, future cleanup if needed
- Genesis mismatch currently logs but does not reject handshake metadata — future policy decision
- Per-item invalid RPC/gossip logging happens silently inside apply_handshake_metadata() — observability tradeoff accepted for now
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.3
v0.7.3 - Peer and Address Canonicalization Hardening
v0.7.3 - Peer and Address Canonicalization Hardening
Status: Released
What Changed
Peer identity is now derived from canonicalized addresses.
This release introduces a dedicated address canonicalization module and hardens the full inbound peer registration path. Malformed handshake identities are dropped before hashing. Stale provisional dial targets are upgraded on every handshake. The identity model is now internally consistent across inbound and outbound paths.
Address canonicalization module (address.rs):
- canonicalize_peer_addr() — wildcard, localhost, IPv6, and hostname normalization using actual transport IP
- canonicalize_rpc_addr() — normalizes RPC host against canonical peer address
- is_valid_peer_addr() — validates canonical address form before identity hashing
Network hardening:
- Inbound handshake drops connections with malformed canonical addresses — identity is never derived from a non-address string
- Inbound peer registration uses canonicalized address with actual transport IP before hashing
Peer manager:
- bind_canonical_dial_target() — explicit dial target upgrade on every handshake
- normalize_peer_address() overwrites inherited dial target on canonical migration
Test coverage:
- 18 address canonicalization tests
- 8 peer manager reconciliation tests
- 77 total tests passing
Deferred
- Gossiped peer address validation
- RPC address validation
What Stays
- Outbound provisional identity based on dial target, reconciled via handshake normalization
- All existing behavior above the transport layer unchanged
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.2
v0.7.2 - TLS 1.3 P2P Transport Encryption
v0.7.2 - TLS 1.3 P2P Transport Encryption
Status: Released
What Changed
P2P transport now uses TLS 1.3.
All inbound and outbound P2P connections are wrapped in TLS 1.3. Certificates are ephemeral — generated in memory at startup, never written to disk, and not persisted across restarts. They are transport artifacts only and do not participate in peer identity.
tls.rs (new):
- generate_tls_config() — ephemeral self-signed server certificate generated in memory at startup
- generate_client_tls_config() — client config with FingerprintVerifier
- cert_fingerprint() — SHA-256 fingerprint extraction for observability
- TLS 1.3 only — no legacy protocol fallback
- Local cert fingerprint logged at startup; peer cert fingerprints logged on every connection
network.rs:
- send_framed_message and read_framed_message generalized over AsyncRead + AsyncWrite + Unpin
- start_listener wraps accepted TCP streams with TlsAcceptor
- connect_and_handle_peer wraps outbound TCP streams with TlsConnector
- broadcast_message wraps broadcast connections with TlsConnector
- TLS configs passed in as shared Arc and Arc
main.rs:
- Server and client TLS configs generated once at startup
- Shared via Arc through all network paths — not regenerated per connection
What This Is Not
- Certificate trust anchoring and fingerprint pinning remain deferred to later hardening work
- RPC sync transport remains unchanged in this release; RPC TLS is deferred
- Mutual TLS is not introduced in this release; certificates remain outside the peer identity model
What Stays
- Peer identity model above transport layer unchanged from v0.7.1
- All 51 tests pass unchanged
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.1
v0.7.1 - Validator IP Hashing and Peer Identity/Transport Separation
v0.7.1 - Validator IP Hashing and Peer Identity/Transport Separation
Status: Released
What Changed
Zero Footprint applied to the network layer.
Raw IP addresses no longer exist as peer identity artifacts. This release separates peer identity (hashed) from peer transport (raw address for TCP only), aligned with the Zero Footprint principle — you cannot leak what you never kept.
Peer address hashing (src/crypto.rs):
- peer_addr_hash(addr, genesis_hash) — epoch-salted hash using 24-hour rotation window
- Salt derived from genesis_hash + current epoch — deterministic, no new state
- Same peer produces same hash within an epoch — dedup works
- Raw IP never stored, never logged as peer identity
Identity/transport separation (src/peer_manager.rs):
- peers HashMap keyed by peer hash — identity layer
- dial_targets HashMap maps hash → raw address — transport layer
- add_peer() takes (peer_hash, dial_addr) — both stored separately
- get_connected_peers() returns hashes — identity only
- get_connected_peer_dial_targets() returns (hash, raw_addr) pairs — transport for broadcast/reconnect
- get_all_known_peers() returns raw dial addresses — gossip stays dialable
- cleanup_stale_peers() removes from both maps together
Inbound peer registration (src/network.rs):
- Inbound peers not registered at socket accept time — no ephemeral source port hashing
- Identity derived from advertised peer_addr in handshake — stable across reconnects
- Dial target resolved via resolve_dial_addr() — handles 0.0.0.0:port wildcard bind addresses
- Outbound provisional identity from dial target hash — reconciled via handshake normalization in main.rs
Handshake reconciliation (src/main.rs):
- declared_hash computed from their_addr — hash-to-hash comparison, not raw-vs-hash
- normalize_peer_address() called only when hashes differ
- normalize_rpc_addr() uses their_addr — raw address space, not hash space
- Known peers from gossip added as hash → raw dial address
Naming cleanup (src/types.rs):
- PeerInfo.address renamed to PeerInfo.peer_hash
- generate_peer_id(addr) parameter renamed to generate_peer_id(peer_identifier)
Known Limitations
- resolve_dial_addr() handles 0.0.0.0:port only — hostname and IPv6 normalization deferred
- Wildcard RPC normalization uses advertised address rather than resolved dial target — deferred
- Outbound provisional identity (hash of dial target) may differ from inbound declared identity until handshake normalization — acceptable for current bootstrap phase
What This Is Not
- Not TLS — transport encryption is v0.7.2
- Not rate limiting — operational hardening is v0.7.2
- Not anonymous membership proof — bootstrap is a private ceremony between trusted partners
Full Changelog: See CHANGELOG.md
Previous Release: v0.7.0
v0.7.0 - TPI Identity Release
v0.7.0 - TPI Identity Release
Status: Released
What Changed
Valid Blockchain is now a TPI chain.
This release removes the last remnants of inherited PoS framing and establishes Three-Party Integrity as the chain's actual consensus identity. TPI is not a variant of an existing mechanism — it is an original design.
Handshake cleanup:
- validator_id removed from peer handshake entirely
- Peer connections are now identity-free at the transport layer
- No validator identity is broadcast at connection time
- TPI block production proves validator legitimacy through chain behavior, not declarations
SPO dropped:
- Stake Pool Operator delegation removed from scope entirely
- delegations removed from ChainState and SnapshotPayload
- The chain has no stake — validator weights are merit-based participation weights, not locked capital
Startup simplified:
- Quorum gating removed — production readiness determined by sync completion
- 120-second validator quorum timeout removed
- sync_triggered AtomicBool removed
- Solo node behavior unchanged — production enabled immediately
- Bootstrap nodes remain temporary scaffolding, removed once peer gossip is self-sustaining
What Stays
- validator_id still used internally in TPI message flow — consensus layer unaffected
- All 51 tests pass unchanged
- Archive, publication, and Arweave sidecar unaffected
Security Note
Bootstrap is a private ceremony between trusted partners. Peer connections carry no validator identity. TPI participation is the proof of presence.
Full Changelog: See CHANGELOG.md
Previous Release: v0.6.7
v0.6.7 - Arweave Archive Publication Sidecar
v0.6.7 - Arweave Archive Publication Sidecar
Status: Released
What's Added
Backend-neutral publication contract (src/publication.rs)
- ArchiveArtifact, PublicationManifest, PublicationReceipt, PublicationStatus
- Immutable manifest written after verified archive write, before prune
- Receipt tracks status: Pending, Processing, Submitted, Failed, SkippedOversize, DeferredChunkingRequired
- Atomic temp-file + rename writes for both manifest and receipt
- Manifest queue and receipt directories separate — no file-moving state machine
Arweave uploader (src/arweave.rs)
- JWK wallet loading from ARWEAVE_JWK_JSON env var
- Deep hash implementation (SHA-384, recursive) per Arweave spec
- RSA-PSS signing with SHA-256 — confirmed correct per Arweave HTTP API docs
- Signing field order verified against official docs: format, owner, target, data_root, data_size, quantity, reward, last_tx, tags
- Merkle data_root computation for chunked data — requires real network validation
- Inline upload only — segments over 8MB receive DeferredChunkingRequired (configurable via ARWEAVE_INLINE_MAX_BYTES)
- Tag schema: App-Name, App-Version, Content-Type, Archive-Type, Chain-Genesis, Segment-Start, Segment-End, Segment-Checksum, Archive-Version
- Tag byte-size guard (2048 byte Arweave limit enforced)
- Transaction id = SHA-256 of signature bytes per Arweave spec
Background publisher loop (main.rs)
- Spawned at startup as independent tokio task — no impact on consensus or archive path
- Scans publish_queue/ every 5 minutes
- Skips Submitted and DeferredChunkingRequired receipts (terminal)
- Retries Failed receipts on next tick
- Logs and retries if receipt file is corrupt rather than silently suppressing
- Node runs normally if ARWEAVE_JWK_JSON is absent — publication is optional
Dev tooling
- src/bin/archive_size_estimator.rs — measures real segment sizes at varying tx/block counts
- src/bin/arweave_smoke_test.rs — validates JWK load and RSA key path compiles and runs
What's Changed
- archive_segment_to_disk() returns ArchiveSegment on success (metadata reused for manifest)
- maybe_archive_and_prune() emits publication manifest after verified write, before prune
- New dependencies: rsa = "0.9", data-encoding = "2", jsonwebkey = "0.3"
- .cargo/audit.toml added — three inapplicable advisories documented and ignored
Policy
- Prune correctness never depends on remote upload success
- Local archive write + verify is the only gate for prune
- Remote publication is best-effort sidecar
Known Limitations
- Merkle data_root correctness requires active network validation with a funded wallet
- Chunked upload (segments > 8MB) deferred to future release
- VIPFS will replace Arweave as the publication backend when ready — sidecar architecture makes this a backend swap, not a validator change
Security Note
Validator testnets should remain private until v0.7.0. See NETWORKING.md.
Full Changelog: See CHANGELOG.md
Previous Release: v0.6.6
v0.6.6 - Archive Lock-Scope and Concurrency Hardening
v0.6.6 - Archive Lock-Scope and Concurrency Hardening
Status: Released
What's Fixed
ChainState lock no longer held during disk I/O
- Archive segment building, writing, and verification previously happened while holding the chain write lock
- This could stall block production and RPC reads during slow disk activity
- Now: only a brief read lock to clone blocks, and a brief write lock to prune. No lock held during file I/O
Archive I/O no longer blocks Tokio worker threads
- Disk writes/reads now run through tokio::task::spawn_blocking
- Keeps the async runtime responsive during archive generation
Duplicate concurrent archive prevention
- archiving_in_progress: Arc<Mutex<HashSet>> guard prevents two tasks from racing on the same archive segment
What's Added
- archive_segment_to_disk() — isolated synchronous archive logic
- tests/archive_tests.rs — 11 new unit tests (checksum validation, version mismatch, block count mismatch, empty-segment rejection, sort-on-build, write/read round trips)
- Clearer archive start/success/failure logging
What's Changed
- maybe_archive_and_prune() is now async, operating on Arc<RwLock>
- Archive work spawned as an independent task, fully decoupled from block production/receipt
- Prune range fixed deterministically at trigger time. Never re-derived from a changed chain tip
Test Coverage
All 51 tests pass (40 existing + 11 new).
Security Note
Validator testnets should remain private until v0.7.0. See NETWORKING.md.
Full Changelog: See CHANGELOG.md
Previous Release: v0.6.5